微信小程序全局事件订阅
微信小程序全局事件订阅
在Vue开发中,我们可能用过eventBus来解决全局范围内的事件订阅及触发逻辑,在微信小程序的开发中我们可能也也会遇到同样的需求,那么我们尝试下在小程序(原生小程序开发)中实现类似eventBus的事件订阅功能。
全局事件订阅
- 全局实例 在Vue中我们有new Vue得到的全局对象,小程序中对应的则是app对象,在小程序组件或者页面中可以通过getApp()获取;
- 事件订阅
声明对象存储事件,示例中使用map存储eventMap,向存储器中存放需要被触发的事件
// 注意 开发阶段热跟新时,eventMap的声明和触发可能存在异步问题,需要阻断eventMap声明在触发之后的情况,这个问题仅限开发阶段存在 on(action, event) { if (eventMap && !eventMap.has(action)) { eventMap.set(action, event) } }
- 事件触发
当业务逻辑需要触发时,调用emit触发指定事件
emit(action, arg) { if (eventMap && eventMap.has(action)) { eventMap.get(action) && eventMap.get(action)(arg) } }
- 事件卸载
当订阅的事件过多或者确定事件不在被触发时,及时卸载事件可以减少内存压力
off(action) { if (eventMap && eventMap.has(action)) { eventMap.delete(action) } }
整体代码如下(文件:app.js):
const eventMap = new Map()
App({
globalData: {
count: 1
},
// 事件订阅
on(action, event) {
if (eventMap && !eventMap.has(action)) {
eventMap.set(action, event)
}
},
// 事件卸载
off(action) {
if (eventMap && eventMap.has(action)) {
eventMap.delete(action)
}
},
// 事件触发
emit(action, arg) {
if (eventMap && eventMap.has(action)) {
eventMap.get(action) && eventMap.get(action)(arg)
}
}
})
页面或者组件中使用
- 订阅on,订阅自定义事件countAdd(自定义事件名),并且传入事件被触发后需要被触发的逻辑,这里的changeCount就是在事件被触发是订阅触发的数据,当然触发事件的参数可以来自emit也可以无参数
const app = getApp()
Page({
data: {
count: app.globalData.count,
},
created() {
// 注册事件
app.on('countAdd', this.changeCount.bind(this))
},
changeCount(count) {
this.setData({
count
})
}
})
- 发布emit,发布自定义事件countAdd(自定义事件名)来触发所有监听该事件的订阅者(既注册了on的组件或者页面),emit携带的参数也会被传递给自定义事件
const app = getApp()
Component({
data: {
count: app.globalData.count,
},
// 触发事件
bindEvent() {
app.emit('countAdd', this.data.count++)
}
})
这里changeCount是最终被触发的事件,countAdd是在订阅服务中自定义的事件名,之所以不使用相同的事件名,主要是区分下。
整体事件触发逻辑如下:
- 先订阅事件 changeCount
- 业务需要触发的时候触发bindEvent
- emit到全局来调用监听的事件