发布订阅的实现

1111

  • 如果图不理解,先看下面的实现,读懂以后看图,就很清楚明了
/** 事件集合 */
type Event = keyof EventsType

/** 事件的参数类型 */
type EventPrams<T extends Event> = EventsType[T]

/** 回掉函数的类型 */
type EventAction<T extends Event> = (data?: EventPrams<T>) => void

/** ------ 以上内容是ts 代码 --------- */
/** 
 * @author ajin
 * @description 发布订阅函数
 */
class SubScribeEvent {
  static instance: SubScribeEvent | null

  /** 所有订阅的事件 */
  allEvents = new Map<Event, EventAction<Event>[]>()

  /** 绑定事件 */
  on (eventName: Event, eventAction: EventAction<typeof eventName >) {
    const hasEvent = this.allEvents.has(eventName)
    if(!hasEvent) {
      this.allEvents.set(eventName, [eventAction])
    }else {
      const curFns = this.allEvents.get(eventName)
      this.allEvents.set(eventName, [...curFns, eventAction])
    }
  }

  /** 解绑事件 */
  off(eventName: Event, eventAction?: EventAction<typeof eventName >) {
    if(!eventAction) {
      this.allEvents.delete(eventName)
    }else {
      const fns = this.allEvents.get(eventName)
      const index = fns.indexOf(eventAction)
      index !== -1 && fns.splice(index, 1)
      this.allEvents.set(eventName, fns)
    }
  }

  /** 触发事件 */
  emit(eventName: Event, params?: EventPrams<typeof eventName>) {
    if(!this.allEvents.has(eventName)) {
      throw new Error(`${eventName} is not defined`)
    }
    const fns = this.allEvents.get(eventName)
    fns.forEach(fn => fn(params))
  }

  /** 是否订阅过某个事件 */
  has(eventName: Event) {
    if(!eventName) return false
    return this.allEvents.has(eventName)
  }

  /** 单例暴露方法 */
  static getSubScribeEvent() {
    if(!this.instance) {
      this.instance = new SubScribeEvent()
    }
    return this.instance
  }
}

export default  SubScribeEvent.getSubScribeEvent()
  • 以上是一个发布订阅的实现
  1. instance 静态属性 ,保存当前SubScribeEvent 的实例,单例模式
  2. on 方法 ,绑定/订阅事件,判断事件是否被绑定过,没有则set,有则push
event.on('closeModal', (p) => { 
   console.log( 'closeModal事件'+p)
})
  1. off 解绑事件,事件触发完以后,都要执行解绑事件操作,否则会造成内存泄露。
  • 注意:一个事件名可能对应多个绑定的事件,所以要指定解除某个事件时,必须要相同的函数引用。
const event1 = (p) => {
	console.log('我是事件1'+p)
}
const event2 = (p) => {
	console.log('我是事件2'+p)
}

event.on('closeModal', event1)

event.on('closeModal', event2)
// 指定解绑event1,
event.off('closeModal', event1) 
// 这样是错误的解绑方式,函数是存在堆内存中
event.off('closeModal', () => {}) 
  1. emit 触发事件 / 发布事件,循环触发所有订阅的事件。
event.emit('closeModal', '触发了')

// 打印 我是事件1触发了
// 打印 我是事件2触发了
  1. has 查询某个事件是否订阅
event.has('closeModal') // true
event.has('otherFn') // false
  1. getSubScribeEvent 是一个静态方法,返回唯一一个实例,单例模式的具体应用。
  • 使用时SubScribeEvent 只能存在一个,如果存在多个,会存在一系列的问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值