vue 3中父组件监听子组件事件需在模板用@事件名绑定函数,子组件用defineemits声明后调用emit触发;事件名推荐短横线格式,defineemits须顶层调用,支持参数验证与解构写法。

在 Vue 3 中,父组件监听子组件通过 emit 抛出的自定义事件,核心就一句话:**在父组件模板中用 @事件名 绑定处理函数,子组件内部调用 emit('事件名', 数据) 触发即可**。整个过程不依赖 ref、不写 $on,简洁直接。
子组件:定义并触发事件
使用 defineEmits 明确声明可抛出的事件(推荐),再在逻辑中调用 emit:
- 数组写法(简单场景):
const emit = defineEmits(['submit', 'cancel']) - 对象写法(带参数验证):
const emit = defineEmits({ submit: (payload) => typeof payload === 'object' }) - 触发时传参:
emit('submit', { id: 123, name: 'Vue' })
父组件:用 @ 绑定并接收数据
在引用子组件的标签上,用 @事件名 语法监听,回调函数参数自动接收子组件传来的值:
- 模板写法:
<childcomponent></childcomponent> - 脚本中定义处理函数:
function handleSubmit(data) { console.log('收到提交数据:', data) } - 支持解构写法:
@submit="(data) => { /* 处理逻辑 */ }"
常见注意事项
避免踩坑,注意这几点:
- 事件名不要用驼峰(如
userClick),建议用短横线格式(user-click),否则父组件需写成@'user-click'才能生效 -
defineEmits是编译时宏,不能出现在条件语句或函数内,必须顶层调用 - 如果子组件未声明该事件(如
emits: ['save']),但执行了emit('delete'),开发模式下会发出警告 - 父子通信是单向的——子组件只能通知父组件,不能直接修改父组件 props
补充:监听子组件生命周期事件
有时需要知道子组件是否挂载完成或即将卸载,有两种方式:
- 用
@hook:mounted(Vue 3 支持,但部分钩子名有变化,如beforeDestroy → beforeUnmount) - 更推荐:子组件自己在
onMounted里emit('mounted'),父组件监听@mounted—— 语义清晰、可控性强、类型友好
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










