defineEmits是Vue 3中声明子组件事件的关键函数,支持数组/对象写法、v-model双向绑定及TS强类型校验,需显式声明才能触发有效事件。
defineEmits 是 Vue 3 组合式 API 中用于声明子组件可触发事件的关键函数,它替代了 Vue 2 的 emits 选项,让子组件的事件接口更清晰、类型更安全(尤其在 TypeScript 中)。
在 setup 或 <script setup> 中调用 defineEmits,传入事件名数组或对象,然后通过返回的函数派发事件:
<script setup>
const emit = defineEmits(['update:modelValue', 'change', 'submit'])
const handleClick = () => {
emit('change', 'new value') // 触发 change,并传参
}
</script>
const emit = defineEmits({
'update:modelValue': (value: string) => typeof value === 'string',
'submit': (data: { id: number; name: string }) => true
})
立即学习“前端免费学习笔记(深入)”;
✅ 注意:校验函数只需返回布尔值,不抛错;Vue 不会拦截非法调用,但会在开发模式下给出警告。
当子组件需要支持 v-model(如自定义输入框),需按约定命名事件:update:xxx。Vue 会自动将 v-model="xxx" 编译为 :xxx="xxx" @update:xxx="val => xxx = val":
v-model 的 prop 名(默认是 modelValue)和对应事件update:modelValue 事件更新父级数据<script setup>
const props = defineProps({ modelValue: String })
const emit = defineEmits(['update:modelValue'])
const handleChange = (e: Event) => {
emit('update:modelValue', (e.target as HTMLInputElement).value)
}
</script>
<template>
<input :value="props.modelValue" @input="handleChange" />
</template>
搭配 defineEmits 的泛型,可让事件参数具备完整类型推导(VS Code 可提示、编译期检查):
const emit = defineEmits<{
(e: 'change', value: string): void
(e: 'error', code: number, msg: string): void
(e: 'init', config: Record<string, any>): void
}>()
(e: '事件名', ...args)
emit('change') 少传/错传参数,TS 会直接报错defineEmits 声明就直接调用 emit —— 否则事件不会被父组件捕获(Vue 3 默认关闭未声明事件的透传)emit(`update:${key}`)),这会破坏类型检查和 IDE 支持'item-added' 而非 'click')