vue3通过ts语法使用组合式API定义props的时候,设置默认值的方法:
export interface Props {
msg: string
labels: string[]
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello', //简单类型直接赋值
labels: () => ['one', 'two'] //由于是数组,所以可以直接这样赋值, 也可以通过匿名函数返回 ['one', 'two']
})
//先定义MessageObj.ts
export interface MessageObj{
variant: string,
message: string
}
//使用
interface MyComponentProps {
modelValue: boolean;
toastObj: MessageObj;
timeOut: number;
}
const props = withDefaults(defineProps<MyComponentProps>(), {
timeOut: 1500,//简单类型直接赋值
modelValue: false,//简单类型直接赋值
toastObj: () => { // 这里需要通过匿名函数的形式返回数据
return {
variant: 'accent',
message: '请求成功'
}
}
});
//错误使用代码
const props = withDefaults(defineProps<MyComponentProps>(), {
timeOut: 1500,//简单类型直接赋值
modelValue: false,//简单类型直接赋值
toastObj: { // 这样是错误用法,我开始一直想这么用,但是一直报错,后来通过官网才找到解决办法,因为 defineProps 返回的是一个readonly类型的数据,不知道为什么,对于复杂类型,不能这么用,但是普通数据类型是可以的
variant: 'accent',
message: '请求成功'
}
});
总结就是:普通的数据类型,可以直接赋值,比如 bool string 等,对于复杂类型需要通过匿名函数返回,但是所有的类型都是可以通过匿名函数返回数据的.
完整解释:
在这里,defineProps<MyComponentProps>() 返回一个包含了你定义的组件属性的只读属性对象。然后,withDefaults 函数被用来为这些属性提供默认值。
关于 timeOut 和 modelValue,它们的默认值被设置为简单类型(1500 和 false),这是因为这些属性的默认值可以直接使用,而不会触发 TypeScript 的只读属性错误。你可以直接在属性对象上设置简单类型的默认值,这是 TypeScript 允许的。
关于 toastObj,这是一个对象类型,你想为它提供默认值。但是,由于 TypeScript 的只读属性特性,如果你直接在对象中提供默认值,TypeScript 会认为这个对象是只读的,而不能被修改。
为了绕开这个问题,你使用了一个匿名函数 () => {...} 来延迟 toastObj 的创建。这样,这个函数会在需要 toastObj 的默认值时被调用,生成一个新的对象。这个新对象并不是定义时的只读属性对象的一部分,因此不会触发 TypeScript 的只读属性错误。实际上,你是在运行时生成了 toastObj 的默认值,而不是在定义时。
所以,总体来说,通过使用函数来延迟对象的创建,你规避了 TypeScript 对只读属性的限制,使得在需要时才生成对象的默认值。这是一种常见的解决方案,确保你能够为对象类型的属性提供默认值而不触发 TypeScript 的只读属性错误。
参考:https://cn.vuejs.org/api/sfc-script-setup.html#default-props-values-when-using-type-declaration
