尽管有些关于事件总线/发布-订阅模式的报道不怎么好,但是在实现程序中相互无关联的部分之间的沟通方面这种模式是非常好的选择。下面我们一起来看一下Vue.js中强大的内建事件总线。

创建事件总线(Event Bus)

首先我们创建一个event bus然后export它,以便其他的模块和组件能够使用它。

//文件->event-bus.js

import Vue from 'vue';
export const EventBus = new Vue();

在这里,我们import一个vue类,然后实例化它并将它export,我们实际上是创建了一个与DOM和程序的其他部分完全解耦的组件,它仅仅只是一个组件所以它非常的轻量。

使用事件总线

既然我们已经创建了事件总线,接下来我们只要将它import到组件中并调用在父子组件中传递信息时相同的方法。

发送事件

假设你有一个组件,任何时候有人点击它时,它需要通知整个程序它被点击了多少次。下面使用EventBus.emit(channel: string, payload1: any, …)来实现它。

//文件->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: () => {
    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>

接收事件

现在,我们可以在程序的其他任何地方import我们之前创建的Event Bus并使用EventBus.$on(channel: string, callback(payload1,…))来监听PleaseClickMe.vue中发送的事件。

// Import the 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,…)),事件触发后将移除事件。

移除事件Listeners

如果我们现在不想再监听PleaseClickMe.vue被点击了多少次,我们可以像下面的代码一样注销事件。

// 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’)传回调参数来移除特定事件(i-got-clicked)上的所有Listeners(clickHandler)
  • 你也可以通过不带任何参数EventBus.$off()来移除事件总线上的所有Listeners。