Props
你最开始学习在 Vue 中定义 props 类型的方式应该是使用诸如 String
、Number
、Boolean
等类型构造函数,这是用于 Vue 的运行时类型检查的。事实上,Vue 仅主要关注组件的 props 名字说什么,以更好地与普通 attribute 区分,即使提供运行时检查也仅仅只会报告 warning 而不会抛出异常导致程序中断。
但从 Vue 3 开始,用户逐渐期望类型检查过程由 TypeScript 和 IDE 提示来完成,因此我们决定放弃对 props 的 type
字段的支持,因为我们认为当我们已经全面使用 TypeScript 时,它并不是非常有用。
💡 注意
Vine 会在生成组件对象的 props
字段时会删除所有类型信息,彻底抛弃运行时检查类型这一过程。
在 VCF 中定义 props 有两种方式,第一种是为函数的第一个形参提供 TypeScript 类型注解,另一种是使用 vineProp
宏。
如果您没有为 VCF 提供形参,并且在 VCF 内部也没有 vineProp
宏的调用,组件的 props
字段将为 {}
。
用类型注解声明
如果你想在 VCF 参数上定义 props,它应该是第一个参数,并为其编写一个 TypeScript 对象字面量类型注解,其中包含您想要定义的所有 props。
我们决定不再支持属性的 type
字段,因为我们认为当我们已经使用 TypeScript 时,它并不是非常有用。
在这种定义方式下,Vine 默认将所有 prop 视为必需的,您可以使用 ?
标记其为可选 prop。
import { SomeExternalType } from './path/to/somewhere'
function MyComponent(props: {
foo: SomeExternalType
bar?: number // 可选属性
baz: boolean
}) { ... }
布尔型转换机制
在编译时,我们必须知道一个属性是否为布尔型,以确定如何处理这样的属性传递:<MyComponent foo />
。在 Web 标准 HTML 中,属性 foo
的值实际上是一个空字符串。
因此,你必须使用字面量 boolean
注解来指定任何布尔型属性,不允许在这里使用其他在别处定义的类型,即使它最终的结果是布尔类型。
function MyComponent(props: {
// ...
isFrontEnd: boolean
isBackEnd: OtherTypeButActuallyBoolean
}) { ... }
vineProp
这是一个用于定义组件的 prop 的编译宏函数。这个想法启发自 Vue Macros。
- 您必须给出一个类型参数来指定 prop 的类型,或者您必须提供一个默认值来推导出类型。
- 如果你要定义一个可选的 prop,请使用
vineProp.optional
。
const foo = vineProp.optional<string>()
vineProp
的第一个参数是 prop 的验证器,它是可选的。
const foo = vineProp<string>()
const title = vineProp<string>(value => value.startsWith('#'))
若要设置带有默认值的 prop,您可以使用
vineProp.withDefault
,验证器是第二个参数。由于 TypeScript 能够自动推断出默认值的类型,您不需要将类型参数传递给它。
就像我们上面在 “布尔型转换机制” 部分所提到的,当您确实需要一个布尔型 prop 时,类型参数应该是一个字面量 boolean
,并且不应该将变量作为默认值传递,而只能传递 true
或 false
字面量。尽管 TypeScript 可以从变量中推断出类型,但 Vine 编译器并没有嵌入 TypeScript 编译器来得知这个 prop 是布尔型的。
// Correct examples
const foo = vineProp.withDefault('bar')
const biz = vineProp.withDefault(someStringVariable)
const dar = vineProp<boolean>()
const bool = vineProp.withDefault(false)
// Incorrect examples
const bad1 = vineProp<SomeBooleanType>()
const bad2 = vineProp.withDefault(someBooleanVariable)