手寫發佈訂閱模式 EventEmitter

手寫發佈訂閱模式 EventEmitter

1.簡介

最近發現好多大廠面試題裏都有手寫發佈訂閱模式 EventEmitter,原因是 vue 和 react 的非父子組件的通信就是靠他實現的,下面是一個簡易版的 EventEmitter。

2.代碼

// 發佈訂閱模式
class EventEmitter {
  constructor() {
    // 事件對象,存放訂閱的名字和事件  如:  { click: [ handle1, handle2 ]  }
    this.events = {}
  }
  // 訂閱事件的方法
  on(eventName, callback) {
    if (!this.events[eventName]) {
      // 一個名字可以訂閱多個事件函數
      this.events[eventName] = [callback]
    } else {
      // 存在則push到指定數組的尾部保存
      this.events[eventName].push(callback)
    }
  }
  // 觸發事件的方法
  emit(eventName, ...rest) {
    // 遍歷執行所有訂閱的事件
    this.events[eventName] &&
      this.events[eventName].forEach(f => f.apply(this, rest))
  }
  // 移除訂閱事件
  remove(eventName, callback) {
    if (this.events[eventName]) {
      this.events[eventName] = this.events[eventName].filter(f => f != callback)
    }
  }
  // 只執行一次訂閱的事件,然後移除
  once(eventName, callback) {
    // 綁定的時fn, 執行的時候會觸發fn函數
    const fn = () => {
      callback() // fn函數中調用原有的callback
      this.remove(eventName, fn) // 刪除fn, 再次執行的時候之後執行一次
    }
    this.on(eventName, fn)
  }
}

3.使用

const event = new EventEmitter()

const handle = (...pyload) => console.log(pyload)

event.on('click', handle)

event.emit('click', 100, 200, 300, 100)

event.remove('click', handle)

event.once('dbclick', function() {
  console.log('click')
})

event.emit('dbclick', 100)


參考鏈接

1.https://www.fed123.com/javascriptnodejs/4681.html

2.https://www.jianshu.com/p/e0575e17de2a

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章