Bus,通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
注意:记得销毁自定义事件,否则容易造成内存泄露。
基本使用
具体实现方式:
var Bus = new Vue();
Bus.$emit("add-todo", {
text: this.newTodoText });
Bus.$on("add-todo", this.addTodo);
Bus.$off("add-todo", this.addTodo);
使用 vue-bus:npm install vue-bus --save
import Vue from "vue";
import VueBus from "vue-bus";
Vue.use(VueBus);
Listen and clean
// ...
created() {
this.$bus.on('add-todo', this.addTodo);
this.$bus.once('once', () => console.log('This listener will only fire once'));
},
beforeDestroy() {
this.$bus.off('add-todo', this.addTodo);
},
methods: {
addTodo(newTodo) {
this.todos.push(newTodo);
}
}
Trigger
// ...
methods: {
addTodo() {
this.$bus.emit('add-todo', {
text: this.newTodoText });
this.$bus.emit('once');
this.newTodoText = '';
}
}
举个栗子
假设兄弟组件有三个,分别是 A、B、C 组件,A 或 B 组件的向 C 组件发送数据。
组件 A:
<template>
<div>
<div>{
{
name}}</div>
<button @click="postData">发给C</button>
</div>
</template>
<script>
export default {
name: "child-a",
data: () => ({
name: "AAA"
}),
methods: {
postData() {
this.$bus.emit("child-a", this.name);
}
}
};
</script>
组件 B:
<template>
<div>
<div>{
{
name}}</div>
<button @click="postData">发给C</button>
</div>
</template>
<script>
export default {
name: "child-b",
data: () => ({
name: "BBB"
}),
methods: {
postData() {
this.$bus.emit("child-b", this.name);
}
}
};
</script>
组件 C:
<template>
<div>
<div>{
{
name.join(",") }}</div>
</div>
</template>
<script>
export default {
name: "child-c",
data: () => ({
name: ["CCC"]
}),
created() {
this.$bus.on("child-a", this.getData);
this.$bus.on("child-b", this.getData);
},
beforeDestroy() {
this.$bus.off("child-a", this.getData);
this.$bus.off("child-b", this.getData);
},
methods: {
getData(data) {
this.name.push(data);
}
}
};
</script>
this.bus.on监听了自定义事件child−a和child−b,因为有时不确定何时会触发事件,一般会在created钩子中来监听,然后beforeDestroy钩子中通过this.bus.on监听了自定义事件child−a和child−b,因为有时不确定何时会触发事件,一般会在created钩子中来监听,然后beforeDestroy钩子中通过this.bus.off注销自定义事件。
vue-bus 实现源码
最后看一下 vue-bus 的源码:
function VueBus(Vue) {
var bus = new Vue();
Object.defineProperties(bus, {
on: {
get: function get() {
return this.$on.bind(this);
}
},
once: {
get: function get() {
return this.$once.bind(this);
}
},
off: {
get: function get() {
return this.$off.bind(this);
}
},
emit: {
get: function get() {
return this.$emit.bind(this);
}
}
});
Object.defineProperty(Vue, "bus", {
get: function get() {
return bus;
}
});
Object.defineProperty(Vue.prototype, "$bus", {
get: function get() {
return bus;
}
});
}