TS泛型+vue双向数据绑定的原理

125 阅读2分钟

泛型

1. 多个泛型变量的情况

  • 泛型的类型变量可以有多个,并且类型变量之间还可以约束
function getData<T,k extends keyof T>(obj:T,key:k){
    return obj[key]
}
getData({name:'张三',age:18},'name')

2.泛型接口

  • 接口也可以配合泛型来使用,以增加其灵活性,增强其复用性
// 泛型接口
interface type<T> {
    id: (val: T) => T
    ids: () => T[]
}

let obj: type<number> = {
    id(val) {
        return 1
    },
    ids() {
        return [1, 2, 3]
    }
}

3.泛型数组

  • 实际上js的数组在ts上就是一个泛型接口

image.png

  • 当我们在使用数组时,TS会根据数组的不同类型,来自动将类型变量设置为相应的类型

4.泛型类

  • class也可以配合泛型来使用

实例化对象需要加类型

// 泛型类
class Person <T>{
    name:T
    say:(a:T,b:T)=>T
}

let P =new Person<number>()
P.name=1

实例化对象不需要加类型

class Person<T>{
    name: T
    say: (a: T, b: T) => T

    constructor(val: T) {
        this.name = val
    }
}
let P = new Person(100)
P.name=1

5.泛型工具类型

  • TS内置了一些常用的工具类型,来简化TS中的一些常见操作,他们都是基于泛型实现的
  1. Partial< Type >(可选类型)
  • 用来构造一个类型,将Type的所有属性设置为可选
interface Props {
    id: string
    children: number[]
}

type PropsType = Partial<Props>

let p1: Props = {
    id: '12',
    children: [1]
}

let p2: PropsType = {
    id: '12',
    children: [1,3]
}
  1. Readonly< Type >(只读类型)
  • 用来构造一个类型将Type的所有属性都设置为只读
interface Props {
    id: string
    children: number[]
}


type PropsType = Readonly<Props>
let p1: PropsType = {
    id: '12',
    children: [1, 3]
}

p1.id=12 //这里会报错 无法为 “id” 赋值,因为它是只读属性   
  1. Pick< Type,Keys >(从Type中选择一组属性来构造新类型)
interface Props {
    id: string
    title: string
    children: number[]
}

type PickProps = Pick<Props, 'id' | 'title'>

Pick工具类型有两个变量:1.选择谁的属性 2.选择哪几个属性

第二个类型变量传入的属性,只能是第一个变量中存在属性

头灶出来的PickProps,只有id和title两个属性类型

  1. Record< Keys,Type > (构造一个独享类型属性键为Keys,属性值为Type)
// 1.使用Record工具
type Recordobj = Record<'a'|'b'|'c',string[]>

// 2.使用传统方法
type Recordobj1={
    a:string[]
    b:number[]
    c:string[]
}

let obj :Recordobj1={
    a:['a'],
    b:[1],
    c:['c']
}

vue双向数据绑定原理

  • Vue数据双向绑定原理是通过数据劫持结合发布者-订阅者模式的方式来实现的,首先是对数据进行监听,然后当监听的属性发生变化时则告诉订阅者是否要更新,若更新就会执行对应的更新函数从而更新视图
class Vue {
  $options;
  _data;
  constructor(options) {
    this.$options = options;
    this._data = options.data;
    this.initData();
  }

  initData() {
    // this   ,   this._data
    let keys = Object.keys(this._data);
    for (let i in keys) {
      let key = keys[i];   //  "name","age"
      Object.defineProperty(this,key,{
        enumerable:true,
        configurable:true,
        set(val){
          this._data[key]=val
        },
        get(){
          return this._data[key]
        }
      })
    }
  }
}

let vm = new Vue({
  data: { name: "张三", age: 21 },
});