• 被迫开始学习Typescript —— class


    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: 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])
      }
    
    • 效果

    简单的state.png

    • 分析

    把 $id 改为 get 访问器的方式,可以实现 readonly 的效果。

    $id 放在 class (myState) 的“原型”上面,可以避免被遍历出来,这样就实现了伪隐藏的效果。

    当然 使用 state.$id 的方式还是可以访问到的,所以是伪隐藏。

    完整项目代码

    https://gitee.com/naturefw-code/nf-rollup-state

  • 相关阅读:
    [UWP]如何使用Fluent Design System (下)
    [UWP]如何使用Fluent Design System (上)
    [UWP]了解IValueConverter
    [UWP]了解TypeConverter
    [UWP]本地化入门
    [WPF]本地化入门
    [UWP]创建一个进度按钮
    [UWP]分享一个基于HSV色轮的调色板应用
    [UWP]使用Writeable​Bitmap创建HSV色轮
    [UWP]理解及扩展Expander
  • 原文地址:https://www.cnblogs.com/jyk/p/16275700.html
Copyright © 2020-2023  润新知