手拉手带你实现事件总线(发布订阅模式)

概述

事件总线是个啥呢?学术性的解说是:事件总线是实现基于事件驱动模式的方式之一,或者可以将其称为“Broker Topology”。事件发送者将事件消息发送到一个中心broker 上,事件订阅者向中心broker 订阅和接收事件,然后再处理接收到的事件。当然,订阅者不仅可以接收和消费事件,它们本身也可以创建事件,并将它们发送到事件总线上。

在前端中主要体现在非父子组件间的通信(当然,父子组件也可以,只是父子组件中我们不会这样做)

事件总线是一种应用程序设计模式,它允许组件向其他组件发布和订阅事件。事件总线通常是一个中心化的架构,允许不同的组件在不彼此直接通信的情况下进行信息交流。当一个组件发布一个事件时,事件总线会将该事件传递给所有已经订阅该事件的组件。这种模式可以帮助解耦不同组件之间的依赖关系,从而使代码更加模块化、易于维护和扩展。在很多框架和库中都有实现事件总线的功能,例如Vue.js中的Vue实例和React中的Redux。

在这里插入图片描述
你要是觉得不好理解,我觉得可以给你举个形象的比喻。比如说五月天即将来到你的城市开演唱会,你想买票去看,也就是你(订阅者)要和门票(发布者)之间产生关联,票务平台 – 大麦,票牛,官方公众号平台等等就充当了事件总线的角色。但是开票就秒光,这时候一个让人又爱又恨的职业就诞生了 — 黄牛。你买不到票,但可以确定的是黄牛手里一定有票,你只需要付出高溢价就能入场,至于中间的辗转各个平台抢购,几点抢,什么座位,内场还是外场还是山顶等等你都不用关心,多少溢价对应多少等级的门票。这中间黄牛就充当了事件总线的功能。当然,这只是一个玩笑,希望大家不要当真,条件允许的情况下大家能在正规的票务平台买就在平台买,不要买黄牛的,黄牛有风险,入手需谨慎!!! 从以上描述就可以看出,事件总线就和中介差不多(当然,只是类比),三个角色,买方,卖方,中间平台,其中买卖双方的角色可以互换。

好了,废话了这么多,言归正传,看代码吧!

class EventBus {
  constructor() {
  	// 用一个对象来保存监听的事件
    this.eventBus = {}
  }

  // 监听事件
  on(eventName, eventCallback, thisArg) {
    let handlers = this.eventBus[eventName] 
    // 针对第一次取到的监听事件为空进行处理
    if (!handlers) {
      handlers = []
      // 引用赋值
      this.eventBus[eventName] = handlers
    }
    // 此时this.eventBus[eventName]也被赋值了,因为他和handlers指向同一块地址 
    handlers.push({
      eventCallback,
      thisArg
    })
  }

  // 取消监听事件
  off(eventName, eventCallback) {
    const handlers = this.eventBus[eventName]
    if (!handlers) return
    const newHandlers = [...handlers]
    for (let i = 0; i < newHandlers.length; i++) {
      const handler = newHandlers[i]
      if (handler.eventCallback === eventCallback) {
        const index = handlers.indexOf(handler)
        handlers.splice(index, 1)
      }
    }
  }
  
  // 触发事件
  emit(eventName, ...payload) {
    const handlers = this.eventBus[eventName] 
    if (!handlers) return
    handlers.forEach(handler => {
      handler.eventCallback.apply(handler.thisArg, payload)
    })
  }
}
const eventBus = new EventBus()
// main.js
eventBus.on("abc", function() {
  console.log("监听abc1", this)
}, {name: "why"})

const handleCallback = function() {
  console.log("监听abc2", this)
}
eventBus.on("abc", handleCallback, {name: "why"})

// utils.js
eventBus.emit("abc", 123)

// 移除监听
eventBus.off("abc", handleCallback)
eventBus.emit("abc", 123)

应用场景

用于跨文件,跨组件之间的通信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值