微信小程序全局事件訂閱
在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到全局來調用監聽的事件