WARNING
需要 vue 3.3.4+
Vue 3.3
defineProps
和defineEmits
1. - 之前
defineProps
和defineEmits
的类型参数位置使用的类型仅限于本地类型,只支持类型字面量和接口
// before hi.vue
interface HiProps {
msg: string
}
defineProps<HiProps>()
- 编译器现在可以解析导入的类型,并支持一组有限的复杂类型
// after hi.vue
import type { HiProps } from './hi'
defineProps<HiProps>()
// hi.d.ts
export interface HiProps {
msg: string
}
- 还可以定义到全局的类型
// global.d.ts
export interface HiProps {
msg: string
}
// hi.vue
defineProps<HiProps>()
Generic Components
使用 <script setup>
的组件现在可以通过 generic
属性接受泛型类型参数
// Generic.vue
<script setup lang="ts" generic="T,U extends string">
defineProps<{
age: T
name: U[]
}>()
</script>
// app.vue
<Generic :age="10" :name="['1', '2', '3']" />
<Generic age="10" :name="['1', '2', '3']" />
defineEmits
More Ergonomic // BEFORE
// EmiterBefore.vue
const emit = defineEmits<{
(e: 'foo', id: number): void
(e: 'bar', name: string, ...rest: any[]): void
}>()
// App.vue
<EmiterBefore @foo="handleEmiterBeforeFoo" @bar="handleEmiterBeforeBar" />
const handleEmiterBeforeFoo = (id: number) => {
console.log(id)
}
const handleEmiterBeforeBar = (name: string, ...rest: any[]) => {
console.log(name, rest)
}
// AFTER
// EmiterAfter.vue
const emit = defineEmits<{
foo: [id: number]
bar: [name: string, ...rest: any[]]
}>()
defineSlots
<script setup lang="ts">
defineSlots<{
default?: (props: { msg: string }) => any
item?: (props: { id: number }) => any
}>()
</script>
<template>
<div>
<slot msg="123"></slot>
<slot name="item" :id="13"></slot>
</div>
</template>
defineModle
// before
<script setup lang="ts">
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
function onInput(e: Event) {
emit('update:modelValue', (e.target as HTMLInputElement)?.value)
}
</script>
<template>
<input :value="modelValue" @input="onInput" />
</template>
// after
<script setup lang="ts">
const modelValue = defineModel()
</script>
<template>
<input v-model="modelValue" />
</template>