vue3子组件向父组件通信核心是defineemits声明事件并用emit触发,支持数组和ts泛型两种写法,父组件通过@事件名监听,未声明事件将自动绑定到根元素。

Vue3 中子组件向父组件通信,核心就是用 defineEmits 声明可触发的事件,再用 emit 函数实际发出。它不是可选项,而是推荐的、类型安全的标配写法。
声明事件:用 defineEmits 明确“我能发什么”
在 <script setup></script> 中调用 defineEmits,告诉 Vue 这个子组件允许对外抛出哪些事件。这相当于提前“备案”,既防拼错,也支持 TypeScript 类型推导。
- 数组写法(基础):适合简单场景,只声明事件名
- 泛型对象写法(推荐,Vue3.3+):能精确约束每个事件的参数类型,编辑器自动提示,报错更早
'submit': (form: { name: string; email: string }) => void
}>()
触发事件:用 emit 函数“喊一嗓子”
声明后拿到的 emit 是一个函数,调用时第一个参数是事件名(必须和声明一致),后续参数是传递给父组件的数据。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 无参事件:
emit('cancel') - 单参事件:
emit('update:count', 12) - 多参或对象传参:
emit('submit', { name: '张三', email: 'z@x.com' })
注意:如果用了泛型写法,传参类型不匹配会在开发阶段直接报 TS 错误,比如把字符串当 number 传给 update:count,IDE 就会标红。
父组件监听:用 @事件名 接收并响应
父组件在使用子组件标签时,用 @事件名 绑定处理函数。Vue 对 update:xxx 类型事件做了语法糖支持:
- 监听
update:count可简写为v-model:count(配合子组件的modelValue等命名规范) - 普通事件如
@submit或@cancel,直接绑定方法即可
@update:count="total = $event"
@submit="onSubmit"
/>
为什么必须声明?不只是为了类型
Vue3 移除了 .native 修饰符,未在 emits 中声明的事件监听器会自动落到子组件根元素上。比如子组件根是 <button></button>,父组件写了 @click 但没在 emits 里声明 click,那这个 click 就会绑定到 button 上——导致原生点击和自定义逻辑同时触发,出现重复执行。
- 所以声明既是文档,也是运行时行为控制的关键
- 尤其涉及
click、input等原生事件透传时,必须显式声明
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










