0%

在小程序中使用Event Bus进行组件间通信

在开发小程序时,我们会遇到在多个组件间要进行通信的情况,而官方只有全局的 global 能够进行全局性的访问,但并不能够解决我们问题,所以一个能实现全局性的组件间通信很有必要。

创建

首先我们需要创建一个用于存储事件的对象,规定我们的Event Bus只有三个方法可以调用,on 方法用于绑定事件,off 方法用于取消绑定,emit 方法用于触发事件:

1
2
3
4
5
6
7
8
9
10
11
12
class EventBus {
constructor() {
// 存储事件
this.EventCache = {};
}
// 绑定事件
on() {}
// 触发事件
emit() {}
// 解绑事件
off() {}
}

绑定事件与解绑事件

在绑定与解绑事件的时候,我们要知道两个元素,一个是事件名称,另一个是对应的处理方式,知道了这两个元素就可以写具体实现了:

1
2
3
4
5
6
7
on(type, handler) {
this.EventCache[type] = handler;
}

off(type) {
delete this.EventCache[type];
}

这样写是有问题的,同一个事件可以在不同的组件间绑定,这就需要一个来区分不同组件的标志。在小程序中,我们知道不同组件之间他们的路由是不同的,所以我们采用路由来区分不同的组件,在组件里我们采用传入 this 的方式来解决,因为在 this 中有一个 __route__ 属性代表当前组件的路由:

1
2
3
4
5
6
7
8
9
on(type, self, handler) {
let cache = this.EventCache[type] || (this.EventCache[type] = {});
cache[self.__route__] = handler;
}

off(type, self) {
let cache = this.EventCache[type], key;
for (key in cache) key === self.__route__ && (delete this.EventCache[type][key])
}

触发事件

事件的触发,需要的是一个事件名称,也许会传入一些参数:

1
2
3
4
5
emit(type, ...param) {
let cache = this.EventCache[type], key;
if (!cache) return;
for (key in cache) cache[key].call(this, ...param)
}

一个完整的Event Bus就完成了,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class EventBus {
constructor() {
this.EventCache = {};
}

on(type, self, handler) {
let cache = this.EventCache[type] || (this.EventCache[type] = {});
cache[self.__route__] = handler;
}

emit(type, ...param) {
let cache = this.EventCache[type], key;
if (!cache) return;
for (key in cache) cache[key].call(this, ...param)
}

off(type, self) {
let cache = this.EventCache[type], key;
for (key in cache) key === self.__route__ && (delete this.EventCache[type][key])
}
}

剩下的就是在组件中使用了

使用

我们将上面的写在一个文件中导出,需要时引入就行了:

1
export class EventBus { ... }

在小程序的入口文件 app.js 中,我们引入,并初始化:

1
2
3
4
5
6
7
const { EventBus } = require('your file path');

App({
event: new EventBus(),
onLaunch: function() {},
...
})

初始化后,在其他组件引入 app ,并调用相应的方法就行了:

1
2
3
4
5
6
7
8
9
10
11
12
13
const app = getApp();

Page({
onLoad() {
app.event.on('EventName', this, () => {});
},
onShow() {
app.event.emit('EventName');
},
onUnload() {
app.event.off('EventName', this);
}
})