在 vue3 中,我们想给 props 声明,有以下几种方式。
Option 方式
首先是 option 方式:
export default defineCompoent({
props: {
type: {
type: String
}
}
})
这样是我们所熟知的,也是 vue2 和 vue3 通用的,在这里我们可以设置任意内容。
Composition 方式
在 vue3 中,因为提供了 setup 方式,所以有了其他方式:
const props = defineProps({
type: {
type: String
}
})
如果使用类型声明的话,还可以使用这样:
const props = defineProps<{type: String}>();
这样更为简洁,这样的方法在使用上都没有问题。
提取出来
如果我们写一个需要打包后给别人使用的组件时,我们很可能需要编写类型提示,此时就需要将 props 提取出来。
我们可以尝试如下:
// props.ts
const componentProps = {
type: {
type: String,
default: ''
},
// ... otherProps
}
// 导出类型
export type ComponentProps = ExtractPropTypes<typeof componentProps>;
通过 vue 提供的类型方法 ExtractPropTypes
,就可以正确导出类型。此时我们可以看到类型提示。
这样就可以了吗?
可选项
试想以下场景:
当我们的 props 为多个时,在创建时,我们在 props 中提供了默认值,用户可以不填。此时,当用户只在组件上挂载某一个属性后,会发现编译器提示缺少其他属性。
看了一下源码,ExtractPropTypes
本身没什么问题,大概率是 TS 机制。查阅后,很多人说套一层 Partial
:
export type ComponentProps = Partial<ExtractPropTypes<typeof componentProps>>;
确实可以,但是这样的方式,在打包后,类型提示不会生效,这相当于我们白写了。
处理默认值
所以我们不能使用 TS 的 Partial
选项。我们可以换一种方式。
- 单独声明
- 单独处理默认值
将它们分开操作就可以了。
// props.ts
export interface ComponentProps {
/**
* 组件类型
*/
type: String,
// ... otherProps
}
// component.vue
import { withDefaults } from 'vue';
const props = withDefaults(defineProps<ComponentProps>(), {
type: 'primary',
// other props if need
})
这样分开操作,就完美处理了声明无法给默认值、打包后无类型提示等问题。而且,这样做之后,因为我们是直接导出的 interface。对于 TypeScript 来说,它可以直接引用,都不用打包二次编译,我们甚至可以得到对应的注释(前提在 tsconfig 中配置了保留注释)。
目前来说,这样的方案是最优解。似乎 withDefaults
就是为了这个问题而来的~
文章评论