Vue 3中自定义事件仅用于子组件向父组件通信,由defineEmits/emit实现,不依赖事件总线;事件总线(如mitt)则用于任意组件间通信,需手动管理订阅与销毁。

Vue 3 中自定义事件本身不通过事件总线传递——它和事件总线是两种独立的通信机制。自定义事件(defineEmits + emit)专用于子组件 → 父组件通信,而事件总线(如 mitt)用于任意组件之间(兄弟、隔代、跨路由等)的消息传递。
自定义事件:只在父子间直接触发
它不依赖全局对象,也不走事件总线。子组件调用 emit('xxx', data),父组件在模板中用 @xxx="handler" 监听,整个过程由 Vue 框架内部调度,无需手动注册/注销。
- 子组件中必须先声明:
const emit = defineEmits(['xxx']) - 触发时直接:
emit('xxx', { msg: 'hello' }) - 父组件监听写在子组件标签上,不是代码里订阅
事件总线:需手动引入 mitt 并管理生命周期
它模拟了 Vue 2 的 $bus,但 Vue 3 没有全局实例,所以要用第三方库 mitt 封装一个中心 emitter。
- 创建
src/eventBus.js:import mitt from 'mitt'; export const emitter = mitt(); - 发送方(任意组件):
emitter.emit('user-login', { id: 123 }) - 接收方(任意组件):
emitter.on('user-login', handler),且必须在onUnmounted中调用emitter.off防止内存泄漏
别混淆:自定义事件 ≠ 事件总线上的事件
虽然都叫“事件”,但它们底层无关:
– 自定义事件名是模板中硬编码的字符串,由 Vue 编译器识别;
– 事件总线的事件名是纯 JS 字符串,完全由开发者定义,不参与 Vue 模板解析。
你不能用 emit('xxx') 让非父级组件收到消息,也不能用 @xxx 监听 emitter.emit() 发出的消息。
立即学习“前端免费学习笔记(深入)”;
什么时候该选哪种?
- 子组件要告诉父组件“我被点了”“数据提交了”→ 用
defineEmits自定义事件 - 登录组件成功后,通知顶部导航栏刷新用户名,同时通知侧边栏更新权限→ 用事件总线
- 表单子组件、弹窗子组件、编辑器子组件需要把状态同步给多个无关父级→ 优先考虑
provide/inject或 Pinia,事件总线仅作轻量临时方案


















