vben源码解析-自定义prop的扩展

283 阅读2分钟

源码

import { CSSProperties, VNodeChild } from 'vue';
import { createTypes, VueTypeValidableDef, VueTypesInterface, toValidableType } from 'vue-types';

export type VueNode = VNodeChild | JSX.Element;

type PropTypes = VueTypesInterface & {
  readonly style: VueTypeValidableDef<CSSProperties>;
  readonly VNodeChild: VueTypeValidableDef<VueNode>;
  // readonly trueBool: VueTypeValidableDef<boolean>;
};
const newPropTypes = createTypes({
  func: undefined,
  bool: undefined,
  string: undefined,
  number: undefined,
  object: undefined,
  integer: undefined,
}) as PropTypes;

// 从 vue-types v5.0 开始,extend()方法已经废弃,当前已改为官方推荐的ES6+方法 https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#the-extend-method
class propTypes extends newPropTypes {
  // a native-like validator that supports the `.validable` method
  static override get style() {
    return toValidableType('style', {
      type: [String, Object],
    });
  }

  static override get VNodeChild() {
    return toValidableType('VNodeChild', {
      type: undefined,
    });
  }
}
export { propTypes };

源码解析

使用 vue-types 来创建和扩展自定义的 prop 类型。下面是对代码的详细解释。

代码解释

  1. 导入依赖

    import { CSSProperties, VNodeChild } from 'vue';
    import { createTypes, VueTypeValidableDef, VueTypesInterface, toValidableType } from 'vue-types';
    
    • CSSProperties 和 VNodeChild 是 Vue 中的类型,用于描述 CSS 样式和虚拟节点。
    • createTypesVueTypeValidableDefVueTypesInterfacetoValidableType 是 vue-types 库中的工具,用于创建和验证 Vue 组件的 prop 类型。
  2. 定义 VueNode 类型

    export type VueNode = VNodeChild | JSX.Element;
    
    • VueNode 可以是 VNodeChild 或 JSX 元素。
  3. 扩展 VueTypesInterface

    type PropTypes = VueTypesInterface & {
      readonly style: VueTypeValidableDef<CSSProperties>;
      readonly VNodeChild: VueTypeValidableDef<VueNode>;
    };
    
    • PropTypes 扩展了 VueTypesInterface,添加了 style 和 VNodeChild 两种自定义的 prop 类型。
  4. 创建新的 PropTypes 实例

    const newPropTypes = createTypes({
      func: undefined,
      bool: undefined,
      string: undefined,
      number: undefined,
      object: undefined,
      integer: undefined,
    }) as PropTypes;
    
    • 使用 createTypes 创建一个新的 PropTypes 实例,并将其类型断言为 PropTypes
  5. 扩展 newPropTypes

    class propTypes extends newPropTypes {
      static override get style() {
        return toValidableType('style', {
          type: [String, Object],
        });
      }
    
      static override get VNodeChild() {
        return toValidableType('VNodeChild', {
          type: undefined,
        });
      }
    }
    
    • 创建一个新的 propTypes 类,继承自 newPropTypes
    • 使用 toValidableType 方法为 style 和 VNodeChild 创建可验证的类型。
  6. 导出 propTypes

    export { propTypes };
    

改进建议

  • 类型注释:确保类型注释准确无误,避免不必要的类型断言。
  • 使用 ES6+ 语法:如代码中提到的,vue-types v5.0 开始推荐使用 ES6+ 语法来扩展类型。

以下是改进后的代码:

import { CSSProperties, VNodeChild } from 'vue';
import { createTypes, VueTypeValidableDef, VueTypesInterface, toValidableType } from 'vue-types';

export type VueNode = VNodeChild | JSX.Element;

interface PropTypes extends VueTypesInterface {
  readonly style: VueTypeValidableDef<CSSProperties>;
  readonly VNodeChild: VueTypeValidableDef<VueNode>;
}

const basePropTypes = createTypes({
  func: undefined,
  bool: undefined,
  string: undefined,
  number: undefined,
  object: undefined,
  integer: undefined,
}) as PropTypes;

const propTypes = {
  ...basePropTypes,
  style: toValidableType('style', {
    type: [String, Object],
  }),
  VNodeChild: toValidableType('VNodeChild', {
    type: undefined,
  }),
};

export { propTypes };

主要改进点

  1. 类型注释:使用 interface 代替 type 来定义 PropTypes,使类型定义更清晰。
  2. 对象扩展:使用对象扩展语法 (...) 来扩展 basePropTypes,而不是创建一个新的类。这符合 ES6+ 的推荐方式。
  3. 简化代码:通过直接扩展对象属性,代码更加简洁和易读。

这样改进后的代码不仅符合现代 JavaScript/TypeScript 的最佳实践,还能更好地利用 vue-types 提供的类型验证功能。