手写发布订阅模式

149 阅读1分钟
class EventEmitter {
  constructor() {
    this.listeners = Object.create(null)
  }
  // 订阅事件
  on = (event, listener) => {
    if (!event || !listener) {
      return
    }
    if (!this.listeners[event]) {
      this.listeners[event] = []
    }
    this.listeners[event].push(listener)
  }
  // 发布事件
  emit = (event, ...args) => {
    if (!this.hasBind(event)) {
      return
    }
    this.listeners[event].forEach(item => {
      item.call(this, ...args)
    })
  }
  // 取消事件
  off = (event, listener) => {
    if (!this.hasBind(event)) {
      return
    }
    if(!listener) {
      delete this.listeners[event]
      return
    }
    this.listeners[event] = this.listeners[event].filter(item => item !== listener)
  }
  // 只订阅一次事件
  once = (event, listener) => {
    function one() {
      listener.call(this, arguments)
      this.off(event, listener)
    }
    this.on(event, one)
  }
  hasBind = event => {
    return this.listeners[event] && this.listeners[event].length
  }
}

// 测试
const baseEvent = new EventEmitter()
function cb(value){
  console.log("hello "+ value)
}
function cb1(value){
  console.log("hello1 "+ value)
}
function cb2(value){
  console.log("hello2 "+ value)
}
function cb3(value){
  console.log("hello3 "+ value)
}
baseEvent.on("click",cb)
baseEvent.on("click",cb1)
baseEvent.on("click",cb2)
baseEvent.on("click",cb3 )

baseEvent.emit("click",'2020')

baseEvent.off("click",cb1)
baseEvent.emit("click",'2020')