# vue3 Props 源码部分解析

# 1、props 定义

export declare type Prop<T, D = T> = PropOptions<T, D> | PropType<T>;

Prop<T, D = T> 这里的意思是指:

T 是入参类型,D 是默认值类型,如果不指定默认值的话,就用 T 的类型进行推断

# 2.PropOptions 的定义

PropOptions<T, D> 这里的入参意思也是一样的,区别在于 PropOptions 的定义

declare interface PropOptions<T = any, D = T> {
    type?: PropType<T> | true | null;
    required?: boolean;
    default?: D | DefaultFactory<D> | null | undefined | object;
    validator?(value: unknown): boolean;
}

疑问:这里为什么 default 需要返回一个工厂类型

答:这里其实为了解决动态获取 props 的传递值的问题,eg:

当组件初始化时,动态的获取 props 的默认值(即 default

interface MyComponentProps {
  myProp?: string;
}
const myPropOptions: PropOptions<string, string> = {
  default: (props: MyComponentProps) => {
    // Dynamic calculation of default value based on props
    return props.myProp ? props.myProp.toUpperCase() : 'Default';
  },
};

# 3.PropType 和 PropConstructor

PropType<T>

export declare type PropType<T> = PropConstructor<T> | PropConstructor<T>[];

PropConstructor

declare type PropConstructor<T = any> = {
    new (...args: any[]): T & {};
} | {
    (): T; //  无参函数
} | PropMethod<T>;

这里的 PropConstructor 意思中,

new (...args: any[]): T & {}; 是指创建一个新的组件时,对应的入参组件所需的构造函数类型 (即第三段代码)

// 定义组件的数据类型
interface MyComponentData {
  message: string;
}
// 定义组件的构造函数类型
interface MyComponentConstructor {
  new (): MyComponentData;
}
// 创建组件实例的函数
function createMyComponent(ctor: MyComponentConstructor): MyComponentData {
  return new ctor();
}
// 使用组件
const instance = createMyComponent(class {
  message = 'Hello, Vue 3!';
});

(): T; // 无参函数 更多的是针对无需传递参数的组件,也不需要构造器,直接返回改组件的计算值即可

第三种就是接下来要介绍的 propMethods 的构造定义

# 4.propMethods

declare type PropMethod<T, TConstructor = any> = [T] extends [
((...args: any) => any) | undefined
] ? {
    new (): TConstructor;
    (): T;
    readonly prototype: TConstructor;
} : never;

propMethods 解决的场景是,当不是通过显式的传值,而是通过函数计算(如 prop 传参中,default 是通过函数计算得知时,他的构造类型应该如何定义),eg:

import { defineComponent, PropType } from 'vue';
// 定义一个构造函数,用于创建 Person 对象
class Person {
  constructor(public name: string) {}
}
// 定义组件的属性类型
interface MyComponentProps {
  myProp: PropType<Person>;
}
// 使用 PropMethod 来声明 myProp 的类型
const MyComponent = defineComponent({
  props: {
    myProp: {
      type: PropMethod,
      default: () => new Person('John'), // 通过普通函数计算默认值
    },
  },
  setup(props) {
    console.log(props.myProp.name); // 输出: John
  },
});

# 5. 总结

以上就是所有关于 vue3 中,props 类型定义的 ts 源码。我个人看下来,最大的一问题是:为什么需要有构造函数的概念?gpt 给出如下例子解释 props 是如何使用的

interface ComponentProps {
  // PropValue 是一个构造函数,它创建一个具有 name 属性的对象
  propValue: new () => { name: string };
}
class MyComponent {
  constructor(props: ComponentProps) {
    // 创建 propValue 属性值的实例
    const instance = new props.propValue();
    console.log(instance.name); // 可以访问 name 属性
  }
}
// 使用 MyComponent,并传入一个具有 name 属性的构造函数
const myComponent = new MyComponent({ propValue: class { name = 'John'; } });

上述代码,其实更多的是关于 defineComponent 的大致原理。

如下是 defineComponent 的两种使用方法

// options syntax
function defineComponent(
  component: ComponentOptions
): ComponentConstructor
// function syntax (requires 3.3+)
function defineComponent(
  setup: ComponentOptions['setup'],
  extraOptions?: ComponentOptions
): () => any

其中 ComponentOptions 是一个包含组件选项的接口,它描述了组件的各种配置,比如 datamethodsprops 等。

ComponentConstructor : 这个是 defineComponent 函数的返回类型。它表示一个对象的构造函数

eg:

import { defineComponent } from 'vue';
// 定义一个组件
const MyComponent = defineComponent({
  data() {
    return {
      message: 'Hello, Vue 3!',
    };
  },
  methods: {
    greet() {
      console.log(this.message);
    },
  },
});
// 创建组件实例
const myInstance = new MyComponent();
myInstance.greet(); // 输出: Hello, Vue 3!

而 ComponentConstructor 这个其实便是 props 的核心构造函数的最外层,简而言之,相当于 defineComponent 的一切入参(ComponentOptions)便是所谓的 propValue ,亦即最初 Prop 的 PropType<T>, 其可返回其组件构造函数,亦或是无需入参只需返回组件结果,亦可返回 default 默认执行的结果。

即:Prop 是一个入参类型,本质上是一个组件的实例化与结果返回

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

神烦大眼怪 微信支付

微信支付

神烦大眼怪 支付宝

支付宝

神烦大眼怪 贝宝

贝宝