每天学一点Vue3

把 nf-state 改为 ts 形式

2022-05-12  本文已影响0人  自然框架

以前 nf-state 是普通 js 的形式,尝试着改为 ts 的形式。

效果不太理想,目前的水平还看不懂 pinia 的源码,所以暂时采用自己的想法来实现。

Typescript 的优点

原生js没有地方写类型的定义,只能用 jsDoc 写注释,但是写来写去就乱了。ts可以明确定义对象的结构,可以更明确一些。

而编辑器(比如vscode)也可以给出提示和代码检查,这种代码检查要比 单纯的ESLint更严格和准确一些。

比如:


/**
 * 内部保存状态的容器
 */
export interface Store {
  [index: string | symbol] : any
}

/**
 * 状态的类型,对象和数组都需要实现这个接口
 * * $id —— 状态标识,string | symbol
 * * _value —— 记录原值,可以是对象,也可以是 function 
 * * isLog —— 是否记录日志。true :记日志;false: 不记日志(默认值)
 * * 内置方法
 * * * $reset —— 重置
 * * * $patch —— 修改部分属性
 * * * set $state —— 整体赋值,会去掉原属性
 * * * $toRaw —— 取原型,不包含内部方法
 * * * get log() —— 获取日志
 * * * 
 * * 
 */
export interface IState {
  /**
   * 状态标识,string | symbol
   */
  get $id(): string | symbol
  
  /**
   * 记录原值,可以是对象,也可以是 function 
   */
  get $_value(): any
  
  /**
   * 是否记录日志。true :记日志;false: 不记日志(默认值)
   */
  $isLog: boolean

  /**
   * 重置
   */
  $reset (): void
  
  /**
   * 修改部分属性
   */
  $patch(_val: any): void
  
  /**
   * 整体赋值,会去掉原属性
   */
  set $state(value: any)
  
  /**
   * 取原型,不包含内部方法
   */
  $toRaw<T>(): T
  
  /**
   * 获取日志
   */
  get $log(): Array<StateLogInfo>
}

/**
 * 日志的类型
 * * {
 * *   time: '时间戳',
 * *   kind: '', // 操作类型
 * *   oldValue: {},
 * *   newValue: {},
 * *   subValue: {}, // 参数
 * *   callFun: '' // 调用的函数名
 * * }
 */
 export interface StateLogInfo {
  time: number,
  kind: string, // 操作类型
  oldValue: any,
  newValue: any,
  subValue: any, // 参数
  callFun: string // 调用的函数名
}

/**
 * 记录状态的变化日志容器,用key来区分
 * * stateLog = {
 * *  key: {
 * *   log: [
 * *     {
 * *       time: '时间戳',
 * *       kind: '', // 操作类型
 * *       oldValue: {},
 * *       newValue: {},
 * *       subValue: {}, // 参数
 * *       callFun: '' // 调用的函数名
 * *     }
 * *   ]
 * *  }
 * * }
 */
export interface StateLog {
  [index: string | symbol] : {
    log: Array<StateLogInfo>
  }
}

/**
 * 创建状态的选项。
 * * isLocal —— true:局部状态;false:全局状态(默认属性);
 * * isLog ——  true:做记录;false:不用做记录(默认属性);
 * * level ——
 * * * 1:宽松,可以各种改变属性,适合弹窗、抽屉、多tab切换等。
 * * * 2:一般,不能通过属性直接改状态,只能通过内置函数、action 改变状态
 * * * 3:严格,不能通过属性、内置函数改状态,只能通过 action 改变状态
 * * * 4:超严,只能在指定组件内改变状态,比如当前用户的状态,只能在登录组件改,其他组件完全只读
 */
export interface StateOption {
  /**
   * true:局部状态;false:全局状态(默认属性);
   */
  isLocal?: boolean, 
  /**
   * true:做记录;false:不用做记录(默认属性);
   */
  isLog?: boolean, // 
  /**
   * 1:宽松,可以各种改变属性,适合弹窗、抽屉、多tab切换等。
   * 2:一般,不能通过属性直接改状态,只能通过内置函数、action 改变状态
   * 3:严格,不能通过属性、内置函数改状态,只能通过 action 改变状态
   * 4:超严,只能在指定组件内改变状态,比如当前用户的状态,只能在登录组件改,其他组件完全只读
  */
  level?: number
}


/**
 * 创建一个状态的参数类型
 */
export interface StateCreateOption {
  state?: any,
  getters?: any,
  actions?: any
}

/**
 * 创建多个状态的类型
 */
export interface StateCreateListOption {
  store: {
    [index: string | symbol]: StateCreateOption | any
  },
  init: () => void
}

好吧,还是各种any。因为状态管理,需要接收各种类型,目前还不知道如何处理,泛型可以解决一部分,剩余的以后再说。

Typescript 的思考

js 实在是太灵活了,可以有各种写法,对各种写法都规定类型,目前的水平还是比较吃力。

ts 好像只能在编写和打包时进行检查,运行时好像无能为力了。

而状态管理,主要实在运行时存入状态和取出状态,这种时候 ts 要如何做类型检查呢?或则,我的想法本身就不对?

小结

目前的水平硬改为 ts,有点痛苦,也许以后会好些。

.d.ts 文件还是不同清楚如何自动生成,所以只好手动,好在对外的函数不是太多。

另外,vite 打包的时候,并没有包括 type 文件,所以,只好手动拷贝一份过去。

满篇的爆红,很头疼。。。

上一篇 下一篇

猜你喜欢

热点阅读