德胜云资讯,添加一些关于程序相关的内容,仅供大家学习交流(https://www.wxclwl.com)
日期:2023/03/24 19:41作者:蔡依婷人气:
上一篇:被迫开始学习Typescript——interface
TS 的 class 看起来和 ES6 的 Class 有点像,基本上差别不大,除了 可以继承(实现)接口、私有成员、只读等之外。
我们可以定义一个 class,设置几个属性,然后设置一个方法,封装 Object.assign 简化reactive 的赋值操作。
创建自己的对象基类 import type { InjectionKey } from vue class BaseObject { $id: string | symbol | InjectionKey<string> name: string age: number constructor (id: string, name: string, age: number) { this.$id = id this.name = name this.age = age } set $state(value: any) { Object.assign(this, value) } } 使用 import { reactive, defineComponent } from vue const _state = new BaseObject(007, jyk) const state = reactive(_state) state.$state = { name: 直接赋值 }看着是不是眼熟?你猜对了!这里参考 Pinia 设置 $state ,实现给 reactive 直接赋值的功能。
reactive 哪都好,只是整体赋值的时候有点郁闷,这里简单封装了一下,实现直接赋值的功能。
上面的方法只是封装了对象,那么数组怎么办呢?这里就需要用到“继承” extends 的用法。
继承 js 的 Array 创建自己的数组类 class BaseArray extends Array { $id: string | symbol | InjectionKey<string> constructor () { // 调用父类的 constructor() super() this.$id = array } set $state(value: any) { this.length = 0 if (Array.isArray(value)) { this.push(...value) } else { this.push(value) } } } 使用const _state2 = new BaseArray() const state2 = reactive(_state2) state2.$state = [ { name: 008 }, { name: 009 } ]这样数组形式的 reactive ,也可以直接赋值了,是不是方便很多?
继承的是原生数组,所以拥有了数组的所有功能。
另外,子类的constructor里面,需要调用 super() 才会有 this。观察上面的两个 class,会发现拥有相同的成员:$id 和 $state。那么要不要约束一下?
如果想要实现约束功能的话,可以定义一个 interface 来实现。
定义接口 interface IState { $id: string | symbol | InjectionKey<string> set $state(value: any) } 实现接口 class BaseObject implements IState { 略 } class BaseArray extends Array implements IState { 略 }这样设置之后,类的成员就要符合接口的定义,不符合的话会出现提示。
虽然可以使用 private、readonly 标识私有成员和只读成员,只是嘛,到目前为止有点鸡肋。因为只是在 TS 的范畴内给出错误提示,但是完全不影响运行。
那么能不能变相实现一下呢?可以的,只是有点绕圈圈,另外似乎不太正规。
我们把 $id 改为只读、伪隐藏成员。
修改一下接口,使用访问器(get)设置 $id interface IState { get $id(): string | symbol | InjectionKey<string> set $state(value: any) } 修改一下对象基类,使用 get 访问器 class BaseObject implements IState { get $id(): string | symbol | InjectionKey<string> 略 } 创建对象实例的函数 function createState(id: string, name: string, age: number) { // 继承 BaseObject 再定义一个class class myState extends BaseObject { constructor (name: string, age: number) { // 调用父类的 constructor() super(name, age) } // 使用 override 覆盖父类 $id override get $id() { return id } } const _state = new myState(name, age) const state = reactive(_state) return state } 使用 const state3 = createState(010, jyk0013, 29) console.log(state3) console.log(state3 - keys, Object.keys(state3)) for (const key in state3) { console.log(key, state3[key]) } 效果 分析把 $id 改为 get 访问器的方式,可以实现 readonly 的效果。
$id 放在 class (myState) 的“原型”上面,可以避免被遍历出来,这样就实现了伪隐藏的效果。
当然 使用 state.$id 的方式还是可以访问到的,所以是伪隐藏。