使用 defineProps/defineEmits 定义带类型的 Props 与 Emits
泛型 defineProps ()、复杂类型、可选 props,以及事件触发的类型声明
使用 defineProps/defineEmits 定义带类型的 Props 与 Emits 是 CoddyKit 上的免费 Vue Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Vue Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Vue Academy 课程共包含 4 节课。
为组件输入和输出添加类型
使用 lang="ts" 后,defineProps 和 defineEmits 宏可以直接接受 TypeScript 类型。这样,组件流入和流出的数据就能在编译时得到检查。
从接口定义 Props
将类型传给 defineProps 泛型。使用接口可以让复杂的 props 结构更易读,也更容易复用。
<script setup lang="ts">
interface Props {
title: string
count: number
}
const props = defineProps<Props>()
</script>内联类型字面量
对于小型组件,直接使用内联对象类型即可,不需要单独定义接口。
<script setup lang="ts">
const props = defineProps<{
label: string
disabled: boolean
}>()
</script>使用 ? 定义可选属性
使用 ? 将属性标记为可选。可选 props 的类型是 T | undefined,父组件可以省略这些属性。
<script setup lang="ts">
interface Props {
title: string
subtitle?: string
}
const props = defineProps<Props>()
</script>复杂的 Prop 类型
Props 可以是数组、联合类型或对象结构,也就是 TypeScript 能够表达的任何类型。
<script setup lang="ts">
interface Props {
items: string[]
size: 'sm' | 'md' | 'lg'
user: { id: number; name: string }
}
const props = defineProps<Props>()
</script>使用 withDefaults 设置默认值
仅包含类型的形式无法保存默认值,因此请将其包装在 withDefaults 中。第二个参数将 prop 名称映射到默认值。
<script setup lang="ts">
const props = withDefaults(defineProps<{
size?: string
count?: number
}>(), {
size: 'md',
count: 0
})
</script>对象和数组的默认值
对象和数组的默认值必须从工厂函数中返回,就像选项式 API 中一样,以避免所有组件共享同一个实例。
withDefaults(defineProps<{
tags?: string[]
}>(), {
tags: () => []
})声明带类型的 Emits
defineEmits 可以接受一种类型,其中以调用签名的形式列出每个事件及其负载。这可以在编译时捕获错误的负载类型。
<script setup lang="ts">
const emit = defineEmits<{
(e: 'change', value: string): void
(e: 'delete', id: number): void
}>()
</script>发送带类型的负载
现在,emit 只接受有效的事件名称和匹配的负载类型。需要字符串却传入数字会导致编译错误。
function rename(name: string) {
emit('change', name) // ok
// emit('change', 123) // type error
}命名元组语法
Vue 3.3+ 支持一种简写的对象形式,其中每个事件都映射到一个由其参数类型组成的元组,比调用签名更加简洁。
<script setup lang="ts">
const emit = defineEmits<{
change: [value: string]
delete: [id: number]
}>()
</script>同时使用 Props 和 Emits
典型的带类型组件会同时声明两者:通过 defineProps 声明输入,通过 defineEmits 声明输出,并对整个数据流进行完整检查。
<script setup lang="ts">
defineProps<{ modelValue: string }>()
const emit = defineEmits<{
'update:modelValue': [value: string]
}>()
</script>快速检查
测试您对带类型 props 和 emits 的了解。
总结
您已经学会了为组件输入和输出添加类型:
- 将接口或内联类型传给 defineProps<T>()。
- 使用 ? 定义可选 props,使用 withDefaults 设置默认值(对象和数组使用工厂函数)。
- defineEmits<T>() 为事件名称和负载添加类型。
- 元组形式(event: [payload])是现代的简写语法。
常见问题解答
「使用 defineProps/defineEmits 定义带类型的 Props 与 Emits」课时是免费的吗?
是的 — 「使用 defineProps/defineEmits 定义带类型的 Props 与 Emits」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Vue Academy 课程的其余内容,请升级到 CoddyKit PRO。 Vue Academy 课程共包含 4 节课。
「使用 defineProps/defineEmits 定义带类型的 Props 与 Emits」这节课中我会学到什么?
泛型 defineProps ()、复杂类型、可选 props,以及事件触发的类型声明 你通过在浏览器中直接运行的动手代码来练习 Vue Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Vue Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Vue Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 defineProps/defineEmits 定义带类型的 Props 与 Emits」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Vue Academy 课中编写并运行代码吗?
能。每节 Vue Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 在 Vue 项目中配置 TypeScript
- 使用 defineProps/defineEmits 定义带类型的 Props 与 Emits
- 为组合式函数与 Ref 添加类型
- 泛型 Vue 组件