1.事件总线介绍
在vue中跨越层级的两个组件进行通信,若使用props传值和$emit触发的方式会十分繁琐,而事件总线的通信方式更适合跨越层级的组件通信。
2.事件总线原理
事件总线可以用一个对象来表示每一个事件 都有一个数组来记录这个事件的监听者
{
"event1": [hander1, hander2],
"event2": [hander1, hander2, hander3],
}
1,若给某个事件添加监听者,就把处理函数添加到这个事件对应的数组中去
2,若给某个事件取消监听者,就从这个事件对应的数组删除这个处理函数
3,若要触发某个事件,就让这个事件对应的数组存放的处理函数依次执行
用class模拟一个事件总线
// 事件总线
class Bus {
constructor() {
// 用来记录事件和监听该事件的数组
this.listeners = {};
}
// 添加指定事件的监听者
$on(eventName, handler) {
this.listeners[eventName].add(handler);
}
// 取消监听事件
$off(eventName, handler) {
this.listeners[eventName].delete(handler);
}
// 触发事件
$emit(eventName, ...args) {
this.listeners[eventName].forEach((fn) => fn(...args));
}
}
3.事件总线的使用
在main.js中,引入事件总线
import Vue from 'vue';
import App from './App.vue';
import router from './router/index.js';
// 将事件总线作为Vue.prototype的属性,方便每个组件中通过this.$bus获取事件总线
Vue.prototype.$bus = new Vue({});
new Vue({
el: '#app',
render: (h) => h(App),
router,
});
直接使用vue实例作为事件总线,是因为vue实例上本身就具有这三个方法($on、$emit、$off)
home.vue中触发事件总线的事件
<template>
<div>
<button @click="handleClick">点击</button>
<!-- 使用test-comp组件 -->
<test-comp></test-comp>
</div>
</template>
<script>
import testComp from './test-comp.vue';
export default {
name: 'Home',
components: {
testComp,
},
methods: {
handleClick(event) {
// 触发事件总线中的事件,并传参数
this.$bus.$emit('my-click', [1, 2]);
},
},
};
</script>
test-comp.vue中订阅事件总线中的事件
<template>
<div class="red"></div>
</template>
<script>
export default {
mounted() {
// 订阅事件总线中的事件,并接受参数(要等home.vue的this.$bus.$emit执行后才能执行)
this.$bus.$on('my-click', (msg) => {
console.log('接受组件home传来的参数msg: ', msg);
});
},
methods: {},
};
</script>