[TOC]
>[success] # TS -- interface 接口
[第一條的參考文章](https://blog.csdn.net/qq_21033779/article/details/79071887)
~~~
1.了解什么是接口:接口只是定義了一些方法,而沒有去實現,多用于程序
設計時,只是設計需要有什么樣的功能,但是并沒有實現任何功能,這些功
能需要被另一個類(B)繼承后,由 類B去實現其中的某個功能或全部功能
'接口定義了多個類的公共行為規范,這些行為是和外部進行交流的通道'
2.瘋狂java 講義中描述接口(這里筆者稍微改動了下):電腦主板上有usb接
口,但是不同時期usb接口遵循不同的協議,必須遵循了這個協議才能享受
對應不同時期usb 版本帶來的體驗,這個規范我們可以理解成接口,他定義
了一些規則,但具體的方法我們實現這個接口的時候各大廠商按照自己優化
去實現,好處是讓規范和實現分離,讓軟件之間面向接口耦合,是一種松耦
合的設計,這樣主板就不會關心這個是那個廠家制造的usb,也不管你的內
部實現,只要你遵循了我的協議,我們就能匹配。'java' 還利用接口的特性
實現了多繼承
3.pyhon 角度來看,pyhon沒有明確接口概念,使用的抽象類來變相實現,
加上本身的多繼承的特性,也讓他可以將接口這個概念和其他語言劃分開
4.上面是通過csdn作者--' leeyan85'和瘋狂java講義書中加上筆者本身略微
學習過pyhon 和 java,在這基礎上通過語言的對比,和描述希望可以對前端
本身沒有接口概念的開發一點幫助
~~~
>[info] ## 開始TS的接口
~~~
1.可選類型 -- 用'?'號修飾
2.索引簽名 -- 可以添加不確定參數
3.限制接口中的參數是只讀 -- readonly
4.接口 數組 和只讀
5.接口定義函數
6.接口做閉包(混合類型)
7.繞過接口的多余參數檢查-- 三種方式
~~~
>[danger] ##### 通過幾個例子了解ts 接口
~~~
1.例子來自'官方文檔',改進了解接口
2.下面的第一個案例是按照官網思路進行改進的為了更加直觀,有一個 方法
用了打印個人信息的,我們用'ts' 約束了 傳遞參數,有幾個分別是什么類型
3.看完下面的案例其實深入思考,可以指定傳入的對象每一個key規定類
型,和傳遞參數,缺點靈活性不高,不能將公共格式參數的提取出來復用
~~~
* 根據官網案例的思路改進
~~~
// 這里用了ts規定了parmasinfo 參數格式
function printPesonInfo(parmasinfo:{name:string,sex:string}) {
console.log(`姓名:${parmasinfo.name }性別:${parmasinfo.sex}`)
}
// 錯誤使用因為沒有使用定義的sex
// let paramsinfo = {name:'wang',age:12}
let paramsinfo = {name:'wang',age:12,sex:'男'}
printPesonInfo(paramsinfo) // 姓名:wang性別:男
~~~
>[danger] ##### 了解接口 -- interface
~~~
1. 使用在變量前聲明'interface'
2. 簡單案例:
聲明一個interface:
interface person {
name: string;
age: number;
}
然后就可以使用這個interface來限制一個對象的類型:
let tom: person = {
name: 'tom',
age: 12
}
3.和剛才比我們解決了缺點中的問題可以公共提取,規范一個系列
~~~
* 所有動物都有一個最基本的信息名字和性別,必須按照這個規范來創建
~~~
interface Baseinfo {
name:string,
sex:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }性別:${parmasinfo.sex}`)
}
// 動物
function printAnimalInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }性別:${parmasinfo.sex}`)
}
let paramsinfo = {name:'wang',age:12,sex:'男'}
printPesonInfo(paramsinfo) // 姓名:wang性別:男
let paramsAnimainfo = {name:'小黑',age:12,sex:'公'}
printAnimalInfo(paramsAnimainfo) // 姓名:小黑性別:公
~~~
>[danger] ##### 可選類型 -- 用'?'號修飾
~~~
1.現在我們發現不是接口中提供的每一個參數我們都需要,為此'TS' 提供了
一種'?' 來修飾,被問號修飾的參數就是可以選傳,不是必須參數
~~~
~~~
interface Baseinfo {
name:string,
sex?:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
let paramsinfo = {name:'wang'}
printPesonInfo(paramsinfo) // 姓名:wang
~~~
>[danger] ##### 索引簽名 -- 可以添加不確定參數
~~~
1.剛才的問號讓我們可以選填一些參數,但是如果需要增加一些不確定
參數就需要使用 '索引簽名'
2.利用這個可以規定你的索引簽名的類型(即使你的索引規定是string類型
但也可以使用數字,案例三有說明)
3.主要注意這里有個問題:需要注意的是,一旦定義了任意屬性,
那么確定屬性和可選屬性的類型都必須是它的類型的子集(案例二)
~~~
* 案例一
~~~
interface Baseinfo {
name:string,
sex?:string,
[other:string]:any
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
// 接口中的索引簽名other 就會收到age
printPesonInfo( {name:'wang',age:13}) // wang
~~~
* 案例二的錯誤示范
~~~
// 錯誤示范
interface Person {
name: string;
age?: number; // 必須是string類型才行,需要是propName類型的子集
[propName: string]: string; // 改正 [propName: string]: any;
}
}
~~~
* 案例三
~~~
interface Person {
name: string;
age?: number; // 必須是string類型才行,需要是propName類型的子集
[propName: string]: any;
}
let tom: Person = {
name: 'Tom',
age: 25,
1: 'male' // 因為key 會調用 自帶的toString 方法
};
~~~
>[danger] ##### 限制接口中的參數是只讀 -- readonly
~~~
1.readonly 和 const 都是只讀,但兩者如何用區別在哪里,首先'readonly '
是'TS' 在接口提出,只針對接口中的參數賦值后就禁止更改,而const 是
es6 提出的針對變量,不讓變量進行更改
2.用'ts' 文檔的總結來說:最簡單判斷該用readonly還是const的方法是看要
把它做為變量使用還是做為一個屬性。 做為變量使用的話用const,若做
為屬性則使用readonly。
~~~
* 使用
~~~
interface Point {
readonly x: number;
readonly y: number;
}
// p1 是接口Point 類型
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error! 已經設置了readonly 屬性所以禁止更改
~~~
>[danger] ##### 接口 數組 和只讀
~~~
1.我們還可以利用接口定義數組位置的類型,和元組不同,元組不僅限制
了類型也限制了最開始賦值時候的長度(push 還是可以往元組添加東西的)
~~~
* 接口定義數組
~~~
// 接口 數組 和只讀
// 定義了一個數組接口,數組第一位必須數字,第二位是字符串
interface ArrInter {
0:number,
1:string
}
let arr: ArrInter = [1,"w",3]
console.log(arr)
~~~
* 接口 數組 和只讀
~~~
// 定義了一個數組接口,數組第一位必須數字,第二位是字符串
interface ArrInter {
readonly 0:number,
1:string
}
let arr: ArrInter = [1,"w",3]
arr[0] = 5 // erro 后續禁止改變
~~~
>[danger] ##### 接口定義函數
~~~
1.接口不止能定義變量值也可以定義函數
~~~
* 將BaseInfo 加工
~~~
// 定義了一個信息接口,里面有姓名,年齡和一個吃的方法返回的類型是string類型
interface BaseInfo{
name:string,
age:number,
eat(food: string):string
}
const personInfo:BaseInfo = {
name:'wang',
age:99,
eat(parmas){
return parmas
}
}
~~~
* 只定義 方法的接口
~~~
1.對于函數類型的類型檢查來說,函數的參數名不需要與接口里定義的名字相匹配
2.函數的參數會逐個進行檢查,要求對應位置上的參數類型是兼容的
~~~
~~~
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
}
~~~
* 類型別名
~~~
// ts箭頭函數不加大括號的含義是 返回 類型
type PersonInfo = (name:string) => string
// 這里箭頭函數是正常的js 表達的意思
let personName:PersonInfo = (name) => name
// 做一個小備注冒號后面等號前面屬于ts定義, (x: number, y: number, z?:number) => number
// 是ts的定義這里=> 不是js箭頭函數
const add2: (x: number, y: number, z?:number) => number = add
~~~
>[danger] ##### 接口做閉包(混合類型)
~~~
1.利用function 也可以定義key的方式
~~~
* 有時候,一個函數還可以有自己的屬性和方法:
~~~
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
~~~
* 編譯后效果
~~~
function getCounter() {
var counter = function (start) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
var c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
~~~
* 案例二 編譯前
~~~
interface Counter {
(): void;
count: number;
}
function getCounter(): Counter {
const c = ()=>{
c.count++
}
c.count = 0
return c
}
~~~
* 編譯后
~~~
function getCounter() {
var c = function () {
c.count++;
};
c.count = 0;
return c;
}
~~~
>[danger] ##### 繞過接口的多余參數檢查-- 三種方式
* 什么是接口的多余參數檢查
~~~
interface Baseinfo {
name:string,
sex?:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
// 如果直接傳遞參數,且傳遞的參數key未在接口中定義會提示錯誤
printPesonInfo( {name:'wang',age:13} ) // 報錯的
~~~
* 第一種解決使用類型斷言
~~~
interface Baseinfo {
name:string,
sex?:string
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
// 利用類型斷言,告訴編譯器我們傳遞的參數 就是Baseinfo 接口的東西
printPesonInfo( {name:'wang',age:13} as Baseinfo ) // wang
~~~
* 第二種 索引簽名
~~~
interface Baseinfo {
name:string,
sex?:string,
[other:string]:any
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
// 接口中的索引簽名other 就會收到age
printPesonInfo( {name:'wang',age:13}) // wang
~~~
* 利用類型兼容性
~~~
interface Baseinfo {
name:string,
sex?:string,
}
// 人
function printPesonInfo(parmasinfo: Baseinfo) {
console.log(`姓名:${parmasinfo.name }`)
}
let paramsinfo = {name:'wang',age:13}
// 類型兼容性就是我們定義的paramsinfo 不管有都少東西,只要包含接口中定義的即可
printPesonInfo(paramsinfo) // 姓名:wang
~~~
- Vue--基礎篇章
- Vue -- 介紹
- Vue -- MVVM
- Vue -- 創建Vue實例
- Vue -- 模板語法
- Vue -- 指令用法
- v-cloak -- 遮蓋
- v-bind -- 標簽屬性動態綁定
- v-on -- 綁定事件
- v-model -- 雙向數據綁定
- v-for -- 只是循環沒那么簡單
- 小知識點 -- 計劃內屬性
- key -- 屬性為什么要加
- 案例說明
- v-if/v-show -- 顯示隱藏
- v-for 和 v-if 同時使用
- v-pre -- 不渲染大大胡語法
- v-once -- 只渲染一次
- Vue -- class和style綁定
- Vue -- filter 過濾器
- Vue--watch/computed/fun
- watch -- 巧妙利用watch思想
- Vue -- 自定義指令
- Vue -- $方法
- Vue--生命周期
- Vue -- 專屬ajax
- Vue -- transition過渡動畫
- 前面章節的案例
- 案例 -- 跑馬燈效果
- 案例 -- 選項卡內容切換
- 案例-- 篩選商品
- 案例 -- 搜索/刪除/更改
- 案例 -- 用computed做多選
- 案例 -- checked 多選
- Vue--組件篇章
- component -- 介紹
- component -- 使用全局組件
- component -- 使用局部組件
- component -- 組件深入
- component -- 組件傳值父傳子
- component -- 組件傳值子傳父
- component -- 子傳父語法糖拆解
- component -- 父組件操作子組件
- component -- is 動態切換組件
- component -- 用v-if/v-show控制子組件
- component -- 組件切換的動畫效果
- component -- slot 插槽
- component -- 插槽2.6
- component -- 組件的生命周期
- component -- 基礎組件全局注冊
- VueRouter--獲取路由參數
- VueRouter -- 介紹路由
- VueRouter -- 安裝
- VueRouter -- 使用
- VueRouter--router-link簡單參數
- VueRouter--router-link樣式問題
- VueRouter--router-view動畫效果
- VueRouter -- 匹配優先級
- vueRouter -- 動態路由
- VueRouter -- 命名路由
- VueRouter -- 命名視圖
- VueRouter--$router 獲取函數
- VueRouter--$route獲取參數
- VueRouter--路由嵌套
- VueRouter -- 導航守衛
- VueRouter -- 寫在最后
- Vue--模塊化方式結構
- webpack--自定義配置
- webpack -- 自定義Vue操作
- VueCli -- 3.0可視化配置
- VueCli -- 3.0 項目目錄
- Vue -- 組件升級篇
- Vue -- 組件種類與組件組成
- Vue -- 組件prop、event、slot 技巧
- Vue -- 組件通信(一)
- Vue -- 組件通信(二)
- Vue -- 組件通信(三)
- Vue -- 組件通信(四)
- Vue -- 組件通信(五)
- Vue -- 組件通信(六)
- Vue -- bus非父子組件通信
- Vue -- 封裝js插件成vue組件
- vue組件分裝 -- 進階篇
- Vue -- 組件封裝splitpane(分割面板)
- UI -- 正式封裝
- Vue -- iview 可編輯表格案例
- Ui -- iview 可以同時編輯多行
- Vue -- 了解遞歸組件
- UI -- 正式使用遞歸菜單
- Vue -- iview Tree組件
- Vue -- 利用通信仿寫一個form驗證
- Vue -- 使用自己的Form
- Vue -- Checkbox 組件
- Vue -- CheckboxGroup.vue
- Vue -- Alert 組件
- Vue -- 手動掛載組件
- Vue -- Alert開始封裝
- Vue -- 動態表單組件
- Vue -- Vuex組件的狀態管理
- Vuex -- 參數使用理解
- Vuex -- state擴展
- Vuex -- getters擴展
- Vuex--mutations擴展
- Vuex -- Action 異步
- Vuex -- plugins插件
- Vuex -- v-model寫法
- Vuex -- 更多
- VueCli -- 技巧總結篇
- CLI -- 路由基礎
- CLI -- 路由升級篇
- CLI --異步axios
- axios -- 封裝axios
- CLI -- 登錄寫法
- CLI -- 權限
- CLI -- 簡單權限
- CLI -- 動態路由加載
- CLI -- 數據性能優化
- ES6 -- 類的概念
- ES6類 -- 基礎
- ES6 -- 繼承
- ES6 -- 工作實戰用類數據管理
- JS -- 適配器模式
- ES7 -- 裝飾器(Decorator)
- 裝飾器 -- 裝飾器修飾類
- 裝飾器--修飾類方法(知識擴展)
- 裝飾器 -- 裝飾器修飾類中的方法
- 裝飾器 -- 執行順序
- Reflect -- es6 自帶版本
- Reflect -- reflect-metadata 版本
- 實戰 -- 驗證篇章(基礎)
- 驗證篇章 -- 搭建和目錄
- 驗證篇章 -- 創建基本模板
- 驗證篇章 -- 使用
- 實戰 -- 更新模型(為了迎合ui升級)
- 實戰 -- 模型與接口對接
- TypeSprict -- 基礎篇章
- TS-- 搭建(一)webpack版本
- TS -- 搭建(二)直接使用
- TS -- 基礎類型
- TS -- 枚舉類型
- TS -- Symbol
- TS -- interface 接口
- TS -- 函數
- TS -- 泛型
- TS -- 類
- TS -- 類型推論和兼容
- TS -- 高級類型(一)
- TS -- 高級類型(二)
- TS -- 關于模塊解析
- TS -- 聲明合并
- TS -- 混入
- Vue -- TS項目模擬
- TS -- vue和以前代碼對比
- TS -- vue簡單案例上手
- Vue -- 簡單弄懂VueRouter過程
- VueRouter -- 實現簡單Router
- Vue-- 原理2.x源碼簡單理解
- 了解 -- 簡單的響應式工作原理
- 準備工作 -- 了解發布訂閱和觀察者模式
- 了解 -- 響應式工作原理(一)
- 了解 -- 響應式工作原理(二)
- 手寫 -- 簡單的vue數據響應(一)
- 手寫 -- 簡單的vue數據響應(二)
- 模板引擎可以做的
- 了解 -- 虛擬DOM
- 虛擬dom -- 使用Snabbdom
- 閱讀 -- Snabbdom
- 分析snabbdom源碼 -- h函數
- 分析snabbdom -- init 方法
- init 方法 -- patch方法分析(一)
- init 方法 -- patch方法分析(二)
- init方法 -- patch方法分析(三)
- 手寫 -- 簡單的虛擬dom渲染
- 函數表達解析 - h 和 create-element
- dom操作 -- patch.js
- Vue -- 完成一個minVue
- minVue -- 打包入口
- Vue -- new實例做了什么
- Vue -- $mount 模板編譯階段
- 模板編譯 -- 分析入口
- 模板編譯 -- 分析模板轉譯
- Vue -- mountComponent 掛載階段
- 掛載階段 -- vm._render()
- 掛載階段 -- vnode
- 備份章節
- Vue -- Nuxt.js
- Vue3 -- 學習
- Vue3.x --基本功能快速預覽
- Vue3.x -- createApp
- Vue3.x -- 生命周期
- Vue3.x -- 組件
- vue3.x -- 異步組件???
- vue3.x -- Teleport???
- vue3.x -- 動畫章節 ??
- vue3.x -- 自定義指令 ???
- 深入響應性原理 ???
- vue3.x -- Option API VS Composition API
- Vue3.x -- 使用set up
- Vue3.x -- 響應性API
- 其他 Api 使用
- 計算屬性和監聽屬性
- 生命周期
- 小的案例(一)
- 小的案例(二)-- 泛型
- Vue2.x => Vue3.x 導讀
- v-for 中的 Ref 數組 -- 非兼容
- 異步組件
- attribute 強制行為 -- 非兼容
- $attrs 包括 class & style -- 非兼容
- $children -- 移除
- 自定義指令 -- 非兼容
- 自定義元素交互 -- 非兼容
- Data選項 -- 非兼容
- emits Option -- 新增
- 事件 API -- 非兼容
- 過濾器 -- 移除
- 片段 -- 新增
- 函數式組件 -- 非兼容
- 全局 API -- 非兼容
- 全局 API Treeshaking -- 非兼容
- 內聯模板 Attribute -- 非兼容
- key attribute -- 非兼容
- 按鍵修飾符 -- 非兼容
- 移除 $listeners 和 v-on.native -- 非兼容
- 在 prop 的默認函數中訪問 this -- ??
- 組件使用 v-model -- 非兼容
- 渲染函數 API -- ??
- Slot 統一 ??
- 過渡的 class 名更改 ???
- Transition Group 根元素 -- ??
- v-if 與 v-for 的優先級對比 -- 非兼容
- v-bind 合并行為 非兼容
- 監聽數組 -- 非兼容