🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
TS 的 class 看起来和 ES6 的 Class 有点像,基本上差别不大,除了 可以继承(实现)接口、私有成员、只读等之外。
参考:https://typescript.bootcss.com/classes.html
基本用法
我们可以定义一个 class,设置几个属性,然后设置一个方法,封装 Object.assign 简化reactive 的赋值操作。
- 创建自己的对象基类
import type { InjectionKey } from 'vue'class BaseObject {$id: string | symbol | InjectionKey<string>name: stringage: numberconstructor (id: string, name: string, age: number) {this.$id = idthis.name = namethis.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 = 0if (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 再定义一个classclass myState extends BaseObject {constructor (name: string, age: number) {// 调用父类的 constructor()super(name, age)}// 使用 override 覆盖父类 $idoverride 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 的方式还是可以访问到的,所以是伪隐藏。
完整项目代码
https://gitee.com/naturefw-code/nf-rollup-state