适用场景
全局事件总线(Global Event Bus)一般用于远距离(非父子)组件之间的数据通信,是 Vue 中全局状态管理方案的一种。
下图中的组 件 B 和 组件 D 之间进行通信,则可以通过 Global Event Bus 来实现。
基本原理
全局事件总线(Global Event Bus)本质上是通过在全局创建一个空的 Vue 实例,当前项目内所有的组件皆可向该实例上注册事件,相应的,在项目内任意组件内触发该事件,即可实现组件之间的通讯。
使用方法
第一步:创建实例
创建一个空的 Vue 实例
export const EventBus = new Vue();
第二步:注册事件
在组件 A 中使用 $on
方法向 EventBus
注册事件
<template>
<div>{{ count }}</div>
</template>
<script>
import { EventBus } from "../eventbus";
export default {
data() {
return {
count: 0,
};
},
methods: {
increaseCount() {
this.count++;
},
},
created() {
EventBus.$on("increase-count", this.increaseCount);
},
};
</script>
第三步: 触发事件
在组件 D 中使用 $emit
方法触发注册在 EventBus
上的事件
<template>
<div>
<button @click="clickHandler">+1</button>
</div>
</template>
<script>
import { EventBus } from "../eventbus";
export default {
methods: {
clickHandler() {
EventBus.$emit("increase-count");
},
},
};
</script>
第四步:解绑事件
经过上面三步之后,我们已经可以实现组件 A 和组件 D 之间的通信啦!但是要注意,我们注册给 EventBus
的事件,需要在组件 A 销毁的时候取消注册
在组件 A 的 beforeDestory
钩子函数中使用 $off
方法取消已注册的事件
<template>
<div>{{ count }}</div>
</template>
<script>
import { EventBus } from "../eventbus";
export default {
data() {
return {
count: 0,
};
},
methods: {
increaseCount() {
this.count++;
},
},
created() {
EventBus.$on("increase-count", this.increaseCount);
},
beforeDestory() {
EventBus.$off('increase-count', this.increaseCount);
}
};
</script>
核心 API
$on
参数:
{string} event
命名需要使用 Kebab Case
{Function} callback
用法: 监听当前实例上的自定义事件。事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
示例:
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
$emit
参数:
{string} eventName
[...args]
触发当前实例上的事件。附加参数都会传给监听器回调。
示例:
只配合一个事件名使用 $emit
:
vm.$emit('事件名')
传递额外的参数使用 $emit
:
const foo = (bar) => console.log(bar);
vm.$on('trigger-foo', foo)
vm.$emit('trigger-foo', 'Hello world')
$off
参数:
{string | Array<string>} event
(只在 2.2.2+ 支持数组)
{Function} [callback]
用法:
移除自定义事件监听器。
- 如果没有提供参数,则移除所有的事件监听器
$emit()
- 如果只提供了事件,则移除该事件所有的监听器
$emit('事件名称')
- 如果同时提供了事件与回调,则只移除这个回调的监听器
$emit('事件名称', 事件处理函数)