js-發佈訂閱模式實現EventBus

Vue2.x中兄弟組件之間傳值能夠使用Vuex來達到目的,若是項目中不須要相似Vuex這樣的庫來處理組件之間的數據通訊,就能夠考慮Vue中的事件總線 ,即 EventBus來通訊。vue

vue2.x中實現實現EventBus

// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()

或者

// main.js
Vue.prototype.$EventBus = new Vue()
複製代碼

由於vue實例中提供了$on、$emit等方法因此只須要建立一個空的vue實例,在組件中經過$on()註冊事件,在另一個組件中經過$emit()去執行對應的事件而且能夠傳參來達到組件之間的通信。web

實現一個簡單的EventBus

const eventBus = () => {
  /* 訂閱器 */
  subs = new Map();

  return {
    subs,

    /** * 註冊事件 * @param {string} type 事件類型 * @param {Function} callback 回調函數 */
    $on (type, callback) {
      const sub = subs.get(type);
      const isEmpty = sub && sub.push(callback);
      if (!isEmpty) {
        subs.set(type, [callback]);
      }
    },

    /** * 觸發事件 * @param {string} type 事件類型 * @param {Any} payload 傳遞的參數 */
    $emit (type, ...payload) {
      (subs.get(type) || []).forEach(fn => { fn(...payload) });
      (subs.get('*') || []).forEach(fn => { fn(...payload) }); /* 全部事件類型都執行 */
    },
    
    /** * 註銷事件 * @param {string} type 事件類型 * @param {Function} callback 回調函數 */
    $off (type, callback) {
      const sub = subs.get(type);
      if (sub) {
        sub.splice(sub.indexOf(callback) >>> 0, 1);
      }
    }
  }
}

module.exports = eventBus
複製代碼

subs訂閱器能夠使用對象或者來Map來實現,Map自帶clear方法能夠清除全部註冊的事件數組

subs = new Map();
複製代碼

其原理就是以事件類型type做爲Map的key值,以數組做爲value值,數組裏面裝的是一個個執行的回調函數,經過$on註冊的事件若是是相同的type就會被push同一個數組當中,調用$emit的時候找到對應的type循環數組執行裏面全部的回調函數。markdown

使用

const eventBus = require('./eventBus')
const emitter = eventBus()

// 註冊change事件
emitter.$on('change', (...payload) => {
  console.log('change', ...payload)
})

// 調用全部事件都會執行這個方法
emitter.$on('*', (...payload) => {
  console.log('all', ...payload)
})

//觸發change事件
emitter.$emit('change', '參數1', '參數2')
複製代碼

運行結果

能夠使用Map自帶的clear清空EventBusapp

emitter.subs.clear() // 清空EventBus
複製代碼
相關文章
相關標籤/搜索