在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)
}
}
})
const app = getApp()
Page({
data: {
count: app.globalData.count,
},
created() {
// 注册事件
app.on('countAdd', this.changeCount.bind(this))
},
changeCount(count) {
this.setData({
count
})
}
})
const app = getApp()
Component({
data: {
count: app.globalData.count,
},
// 触发事件
bindEvent() {
app.emit('countAdd', this.data.count++)
}
})
这里changeCount是最终被触发的事件,countAdd是在订阅服务中自定义的事件名,之所以不使用相同的事件名,主要是区分下。