VUE支持可切换的卡片布局,但是各组件之间的通信可能变得复杂。事件总线/发布-订阅模式是一种让应用程序的不相关部分相互通信的方式。在 Vue2 中,通过事件总线,我们可以让各组件彼此通信。
项目目录结构
my-vue-app/
├── src/
│ ├── components/
│ │ ├── ComponentReceiver.vue
│ │ └── ComponentSender.vue
│ ├── eventBus.js
│ ├── App.vue
│ └── main.js
└── package.json
实现事件总线
1、创建事件总线文件(EventBus.js)
import Vue from 'vue';
// 创建一个新的 Vue 实例作为事件总线
const EventBus = new Vue()
export default EventBus
2、发送事件的组件(ComponentSender.vue)
<template>
<button @click="sendMessage">发送全局消息</button>
</template>
<script>
import EventBus from '@/EventBus';
export default {
data () {
return {
clickCount:0
}
},
methods: {
sendMessage() {
this.clickCount++
EventBus.$emit('event-name', { text: `Hello from Sender:${this.clickCount}` });
}
}
}
</script>
3、接收事件的组件(ComponentReceiver.vue)
<template>
<div>
<p>接收到的消息:{{ message }}</p>
</div>
</template>
<script>
import EventBus from '@/EventBus';
export default {
data() {
return {
message: ''
};
},
created(){
// 监听事件
EventBus.$on('event-name', this.handleMessage);
},
beforeDestroy() {
debugger
// 组件销毁前移除事件监听,避免内存泄漏
EventBus.$off('event-name', this.handleSimpleMessage)
},
methods: {
handleMessage(payload) {
this.message = payload.text;
console.log('收到全局消息:', payload);
}
}
}
</script>
4、在父组件中使用(App.vue)
template>
<div id="app">
<sender/>
<receiver/>
</div>
</template>
<script>
import sender from '@/components/ComponentSender'
import receiver from '@/components/ComponentReceiver'
export default {
name: 'App',
components:{
sender,
receiver
}
}
</script>
<style>
#app {
text-align: center;
margin-top: 60px;
}
</style>
关键点说明
1、事件总线创建:使用一个空的 Vue 实例作为中央事件总线
2、发送事件:使用 EventBus.$emit('事件名', 参数) 发送事件
3、接收事件:使用 EventBus.$on('事件名', 回调函数) 监听事件
4、移除监听:在组件销毁前使用 EventBus.$off 移除监听,防止内存泄漏
5、参数传递:可以传递字符串、数字、对象等各种类型的数据
总结
在Vue2中事件总线作为一种轻量级的解决方案(不增加额外依赖,直接使用Vue内置功能)可以实现跨组件通信,具有简单易用、灵活性强(可以传递任何类型的数据、支持一对多的通信模式)和实时性(事件触发后立即通知所有监听者)特点。
在Vue3中已删除$on、$off和$once方法,这些方法主要用于 Vue 2.x 中基于 Options API 的事件监听。Vue3推荐使用mitt,mitt是一个轻量级的事件库,适用于全局事件通信。