本文翻译自 Creating a Global Event Bus with Vue.js
尽管 EventBus 或发布-订阅模式的开发方式有时备受诟病,但对于应用程序中联系性低的部分来说,它的确是一个极好的通信方式。但是与其引用第三方库来增大我们项目的体积,何不尝试一下 Vue 内置的、强大的 event bus 呢?
事实证明,Vue 组件中所使用的事件系统 同样可以脱离开来单独使用。
你需要做的第一件事,是创建一个 event bus 并将它导出到某个地方,以便其他模块或组件使用。或许这一部分可能会有点棘手?
// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();
然而这非常简单。你只需要将 Vue 引入并导出它的一个示例(在这个例子中,我把它命名为 EventBus
)。你实际上得到的是一个和 DOM 以及应用中其他部分完全分离的组件。它只存在一些实例方法,所以非常地轻量。
现在你已经创建好了 event bus,你只需要做的是将它引入到组件中,并在父子组件传递消息进行通信时调用相同的方法。
假设你有一个这样的组件:当它被点击的时候,需要将它被点击的次数通知到整个应用中。你可以使用这个方法来实现:EventBus.emit(channel: string, payload1: any, …)
。
这里使用的是 Vue SFC,但是你可以使用任何方法来创建你想要的组件。
<!-- PleaseClickMe.vue -->
<template>
<div class="pleeease-click-me" @click="emitGlobalClickEvent()"></div>
</template>
<script>
// Import the EventBus we just created.
import { EventBus } from './event-bus.js';
export default {
data() {
return {
clickCount: 0
}
},
methods: {
emitGlobalClickEvent() {
this.clickCount++;
// Send the event on a channel (i-got-clicked) with a payload (the click count.)
EventBus.$emit('i-got-clicked', this.clickCount);
}
}
}
</script>
现在,你可以在应用中的任何地方引入 EventBus
并通过这个方法来监听 PleaseClickMe.vue
发布的频道 i-got-clicked
:EventBus.$on(channel: string, callback(payload1,…))
// the-kindly-script.js
// 引入 EventBus
import { EventBus } from './event-bus.js';
// Listen for the i-got-clicked event and its payload.
EventBus.$on('i-got-clicked', clickCount => {
console.log(`Oh, that's nice. It's gotten ${clickCount} clicks! :)`)
});
如果你只想监听第一次发出的事件,可以使用
EventBus.$once(channel: string, callback(payload1,…))
。
如果某些组件已经疲于监听 PleaseClickMe.vue
发出的事件,你可以像这样从对应的频道中注销他们的 handle 方法。
// Import the EventBus we just created.
import { EventBus } from './event-bus.js';
// The event handler function.
const clickHandler = function(clickCount) {
console.log(`Oh, that's nice. It's gotten ${clickCount} clicks! :)`)
}
// Listen to the event.
EventBus.$on('i-got-clicked', clickHandler);
// Stop listening.
EventBus.$off('i-got-clicked', clickHandler);
你也可以通过这个方法来移除某一个事件的所有监听器:
EventBus.$off(‘i-got-clicked’)
如果你需要删除 EventBus 中的所有频道的所有监听器,你可以直接使用EventBus.$off()