Vue子组件向父组件传值通过自定义事件实现:子组件用$emit抛出事件,父组件用@绑定监听;命名需camelCase声明、kebab-case绑定;支持单/多参数及对象传递;Vue 3中defineEmits可做TS类型校验。

Vue 中子组件向父组件传值,核心就是自定义事件。它不依赖任何状态管理库,轻量、解耦、语义清晰。关键在于子组件用 $emit 主动“抛出”事件,父组件用 @事件名 被动“捕获”,中间还可做类型约束和参数校验。
事件触发与监听:命名与绑定规则
子组件内推荐用 camelCase(如 submitSuccess)定义事件名,便于 JS 逻辑书写;父组件模板中必须转为 kebab-case(如 @submit-success)绑定——这是 Vue 的自动转换机制,不是可选项。
- 子组件写法:
<button @click="$emit('inputChange', value)"> - 父组件写法:
<ChildComponent @input-change="onInputChange" /> - 支持修饰符,例如
@submit-success.once表示只响应一次
参数传递:单个、多个与结构化数据
所有传给 $emit 的参数,都会按顺序原样交给父组件的事件处理器。无需额外解析或包装。
- 单参数直接接收:
this.$emit('update', 'new value')→ 父组件fn(val) { console.log(val) } - 多参数也直接接收:
this.$emit('range', 10, 20, 'px')→ 父组件fn(start, end, unit) { ... } - 推荐传对象,提升可读性与扩展性:
this.$emit('userLogin', { id: 123, token: 'abc' })
Vue 3 的 defineEmits + 类型校验(TS 友好)
在 script setup 中,使用 defineEmits 声明事件及参数类型,既提高可维护性,又让 IDE 和 TypeScript 编译器能提前报错。
立即学习“前端免费学习笔记(深入)”;
- 基础声明:
const emit = defineEmits(['save', 'cancel']) - 带类型校验:
const emit = defineEmits({ save: (data: { title: string; done: boolean }) => true }) - 调用时若传参类型不符,TS 会直接提示错误,比如
emit('save', { title: 123 })就会报错
Vue 2 的 $emit 与校验补充说明
Vue 2 没有内置类型声明能力,但可通过文档注释、运行时断言或 ESLint 插件辅助校验。实际开发中建议:
- 统一约定事件命名与参数结构(例如所有
change类事件都传{ key, value, oldValue }) - 在
$emit前加简单判断:if (typeof value === 'string') this.$emit('inputChange', value) - 配合
props校验思路,在事件处理器里做防御性处理,比如if (!data?.id) return


















