Vue 2 中非父子组件通信需借助共享的事件总线(Event Bus),即一个不挂载的 Vue 实例,发送方用 $emit 发布事件,接收方用 $on 监听并在 beforeDestroy 中用 $off 清除监听以防内存泄漏。

在 Vue 2 的 Options API 中,$emit 和 $on 本身是实例方法,但它们**不能直接跨组件调用**——因为每个组件的实例彼此隔离。要实现非父子组件通信,必须借助一个**共享的 Vue 实例作为事件总线(Event Bus)**,它充当“中转站”,让任意组件都能向它发事件、从它收事件。
创建全局事件总线
新建一个文件(如 src/utils/EventBus.js),导出一个空的 Vue 实例:
import Vue from 'vue' export default new Vue()
这个实例不挂载到 DOM,只负责事件的触发与监听,所有组件都能导入并使用它。
发送方组件:用 $emit 发布消息
在需要传出数据的组件(比如 Button.vue)中:
立即学习“前端免费学习笔记(深入)”;
使用 `@ainative/vue-sdk` 为 Vue 3 应用添加 AI 聊天功能。适用于以下场景:(1) 安装 `@ainative/vue-sdk`,(2) 在 Vue 组件中使用 `useChat` 组合式函数,(3) 提供……
- 导入 EventBus:
import EventBus from '@/utils/EventBus' - 在 methods 中调用
EventBus.$emit(事件名, 数据) - 推荐在用户交互(如点击)时触发,避免在 created/mounted 中误发
示例:
methods: {
handleClick() {
EventBus.$emit('update-user-info', { name: '张三', age: 28 })
}
}
接收方组件:用 $on 监听消息
在需要接收数据的组件(比如 Profile.vue)中:
- 同样导入 EventBus
- 在
created或mounted钩子中调用EventBus.$on(事件名, 回调) - 务必在
beforeDestroy中调用$off清除监听,防止内存泄漏
示例:
created() {
EventBus.$on('update-user-info', (payload) => {
this.userInfo = payload
})
},
beforeDestroy() {
EventBus.$off('update-user-info')
}
注意事项和常见问题
事件总线轻量易用,但有明确适用边界:
- 事件名建议用唯一字符串(如
'user/login-success'),避免命名冲突 - 不要在
data或computed中直接调用$on,必须放在生命周期钩子里 - 若监听函数用了箭头函数,
this指向正确;若用普通函数,需注意上下文绑定 - 多个组件可同时监听同一事件(一对多),但无法保证执行顺序
- 复杂状态管理或多人协作项目,应优先考虑 Vuex,事件总线仅适合简单通知类场景

















