手写简单版本的EventBus

44 阅读1分钟
type eventsType = {
  [key: string]: Array<Function>
}

export class EventBus {
  private events: eventsType
  private onceEvents: eventsType

  constructor() {
    this.events = {}
    this.onceEvents = {}
  }

  // on 触发
  on(type: string, fn: Function) {
    const events = this.events
    if (!Reflect.has(events, type)) events[type] = []
    events[type].push(fn)

    console.log(this.events)
  }

  // once 触发
  once(type: string, fn: Function) {
    const onceEvents = this.onceEvents
    if (!Reflect.has(onceEvents, type)) onceEvents[type] = []
    onceEvents[type].push(fn)
  }

  // 解绑事件
  off(type: string, fn?: Function) {
    if (type === '*') {
      this.events = {}
      this.onceEvents = {}
      return
    }

    if (!fn) {
      // 清空所有事件
      this.events[type] = []
      this.onceEvents[type] = []
    } else {
      // 解绑单个事件
      const fnList = this.events[type]
      const onceFnList = this.onceEvents[type]

      if (fnList && fnList.length) {
        this.events[type] = fnList.filter((curFn) => curFn !== fn)
      }

      if (onceFnList && onceFnList.length) {
        this.events[type] = fnList.filter((curFn) => curFn !== fn)
      }
    }
  }

  // emit
  emit(type: string, ...args: any[]) {
    const fnList = this.events[type]
    const onceFnList = this.onceEvents[type]

    if (fnList && fnList.length) {
      fnList.forEach((fn) => fn(...args))
    }
    if (onceFnList && onceFnList.length) {
      onceFnList.forEach((fn) => fn(...args))
      this.onceEvents[type] = []
    }
  }
}

export const bus = new EventBus()