[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 合并行为 非兼容
- 监听数组 -- 非兼容