.vue-loader @ ^17.1.0(如果使用 webpack 或 vue-cli)
<script setup lang="ts"> import type { Props } from './foo' // imported + intersection type defineProps<Props & { extraProp?: string }>() </script>注意,复杂类型支持是基于AST的,因此不是 100% 全面的。不支持一些需要实际类型分析的复杂类型,例如条件类型。可以对单个 props 的类型使用条件类型,但不能对整个 props 对象使用条件类型。
<script setup lang="ts" generic="T"> defineProps<{ items: T[] selected: T }>() </script>generic 的值与 TypeScript 中 <...> 之间的参数列表完全相同。例如,可以使用多个参数、extends约束、默认类型和引用导入类型:
<script setup lang="ts" generic="T extends string | number, U extends Item"> import type { Item } from './types' defineProps<{ id: T list: U[] }>() </script>这个功能以前需要显式地选择,但现在在最新版本的 volar / vue-tsc 中已经默认启用了。
// 堆代码 duidaima.com const emit = defineEmits<{ (e: 'foo', id: number): void (e: 'bar', name: string, ...rest: any[]): void }>()该类型与 emit 的返回类型相匹配,但编写起来有点冗长和笨拙。3.3 引入了一种更符合人体工程学的声明具有类型的 emit 的方法:
const emit = defineEmits<{ foo: [id: number] bar: [name: string, ...rest: any[]] }>()在类型字面量中,键是事件名称,值是指定附加参数的数组类型。虽然不是必需的,但可以使用带标签的元组元素来明确表示,就像上面的示例中一样。调用签名语法仍然受支持。
<script setup lang="ts"> defineSlots<{ default?: (props: { msg: string }) => any item?: (props: { id: number }) => any }>() </script>defineSlots() 只接受类型参数,不接受运行时参数。类型参数应该是类型字面量,其中属性键是插槽名称,值是插槽函数。该函数的第一个参数是插槽期望接收的 props,其类型将用于模板中的插槽 props。defineSlots 的返回值与 useSlots 返回的插槽对象相同。
<script setup> import { watchEffect } from 'vue' const { msg = 'hello' } = defineProps(['msg']) watchEffect(() => { // 在 watchers 和 computed getters 中访问 `msg` // 将其作为依赖项进行跟踪,就像访问 `props.msg` 一样 console.log(`msg is: ${msg}`) }) </script> <template>{{ msg }}</template>defineModel
<script setup> const props = defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) console.log(props.modelValue) function onInput(e) { emit('update:modelValue', e.target.value) } </script> <template> <input :value="modelValue" @input="onInput" /> </template>3.3 使用新的 defineModel 宏简化了使用。宏会自动注册一个 prop,并返回一个可以直接改变的 ref:
<script setup> const modelValue = defineModel() console.log(modelValue.value) </script> <template> <input v-model="modelValue" /> </template>
<script setup> defineOptions({ inheritAttrs: false }) </script>使用 toRef 和 toValue 实现更好的 getter 支持
// 相当于 ref(1) toRef(1) // 创建一个 readonly ref,在 .value 访问时调用 getter toRef(() => props.foo) // 按原样返回现有 refs toRef(existingRef)使用 getter 调用 toRef 类似于 computed,但是当 getter 只执行属性访问而没有昂贵的计算时,可以更高效。
toValue(1) // --> 1 toValue(ref(1)) // --> 1 toValue(() => 1) // --> 1toValue 可以在组合式函数中代替 unref,以便组合式函数可以接受 getter 作为响应式数据源:
// 以前:分配不必要的中间引用 useFeature(computed(() => props.foo)) useFeature(toRef(props, 'foo')) // 现在:更高效和简洁 useFeature(() => props.foo)toRef 和 toValue 之间的关系类似于 ref 和 unref 之间的关系,主要区别在于 getter 函数的特殊处理。