Vue 事件总线(Event Bus)是一种用于非父子组件间通信的模式,它通过一个共享的 Vue 实例作为中央事件总线,允许组件之间触发和监听自定义事件。
核心概念
- 作用:解决跨层级组件(兄弟组件、远房组件)之间的通信问题。
- 原理:创建一个全局的 Vue 实例作为事件中心,组件通过
$emit
触发事件,其他组件通过$on
监听事件。
使用步骤
1. 创建事件总线
在 Vue 2 中,通常将其挂载到 Vue 原型上以便全局访问:
// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();// 或在 main.js 中全局挂载
Vue.prototype.$eventBus = new Vue();
2. 触发事件(发送数据)
在需要发送事件的组件中,使用 $emit
:
<script>
export default {methods: {sendMessage() {// 触发事件,传递数据this.$eventBus.$emit('custom-event', { data: 'Hello from Component A!' });}}
}
</script>
3. 监听事件(接收数据)
在需要接收事件的组件中,使用 $on
监听:
<script>
export default {created() {// 监听事件,接收数据this.$eventBus.$on('custom-event', (payload) => {console.log('Received:', payload.data); // 输出:Hello from Component A!});},beforeDestroy() {// 组件销毁前移除监听,避免内存泄漏this.$eventBus.$off('custom-event');}
}
</script>
注意事项
- 移除监听:务必在组件销毁前(
beforeDestroy
或 Vue 3 的beforeUnmount
)使用$off
移除事件监听,否则可能导致内存泄漏。 - 命名冲突:事件名建议使用唯一标识(如命名空间),避免不同组件间的冲突。
- 替代方案:在 Vue 3 中,官方移除了
$on
、$off
等方法,推荐使用第三方库(如mitt
)或provide/inject
+reactive
实现类似功能。
Vue 3 中的替代方案
Vue 3 不再支持事件总线,但可以通过以下方式实现类似功能:
使用 mitt
库
// eventBus.js
import mitt from 'mitt';
export const emitter = mitt();// 组件A触发事件
emitter.emit('event-name', data);// 组件B监听事件
emitter.on('event-name', (data) => { /* ... */ });// 组件销毁时移除监听
emitter.off('event-name');
优缺点
- 优点:简单快捷,适合小型项目或简单场景。
- 缺点:大型项目中容易导致事件流混乱,难以调试,建议复杂场景使用 Vuex/Pinia。
通过事件总线,你可以轻松实现跨组件通信,但需注意合理使用以避免维护问题。