JavaScript实现发布-订阅模式

JavaScript实现发布-订阅模式

1.实现Bus类

//自定义中央事件总线(Vue中是默认已经实现了$bus的功能)---下面的实现我是从Vue双向数据绑定底层原理那受到了启发
class Bus {
  constructor() {
    this.callbacks = {}; //存放事件,每个事件属性又都是一个对象,存放当前事件的所有回调
    this.callbackEventId = 0; //每次自增
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || {};
    this.callbacks[name][++this.callbackEventId] = fn;
    return this.callbackEventId;
  }
  $emit(name, ...args) {
    for (let id in this.callbacks[name]) {
      this.callbacks[name][id](...args);
    }
  }
  $off(name, id = undefined) {
    if (id == undefined) {
      // 如果只提供了name参数,则只会移除该事件相关的监听器;
      delete this.callbacks[name];
    } else {
      // 如果同时提供了name和id 参数,则只会移除指定事件及回调函数的监听器。
      delete this.callbacks[name][id];
      if (Object.keys(this.callbacks[name]).length == 0) {
        delete this.callbacks[name];
      }
    }
  }
  //清空所有的监听器
  $offs() {
    this.callbacks = {};
  }
}

2.测试一下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>测试发布订阅模式</title>
  </head>
  <body>
    <button onclick="publishEvent1()">发布事件1</button>
    <button onclick="publishEvent2()">发布事件2</button>
    <button onclick="closeEventA()">关闭A</button>
    <button onclick="closeEventB()">关闭B</button>
    <button onclick="closeEventC()">关闭C</button>
    <button onclick="closeEventD()">关闭D</button>
    <button onclick="closeEventAll()">关闭all</button>
    <button onclick="subscribeEvents()">ABCD订阅事件</button>
    <script src="./bus.js"></script>
    <script>
      // 使用示例
      const bus = new Bus();
      function subscribeEvents() {
        // 订阅事件
        let eventA = bus.$on("myEvent1", (data) => {
          console.log("a订阅的事件1被触发了:", data);
        });
        let eventB = bus.$on("myEvent1", (data) => {
          console.log("b订阅的事件1被触发了:", data);
        });
        let eventC = bus.$on("myEvent2", (data) => {
          console.log("c订阅的事件2被触发了:", data);
        });
        let eventD = bus.$on("myEvent2", (data) => {
          console.log("d订阅的事件2被触发了:", data);
        });
      }
      subscribeEvents();
      function publishEvent1() {
        // 发布事件
        bus.$emit("myEvent1", "hello1!");
      }
      function publishEvent2() {
        // 发布事件
        bus.$emit("myEvent2", "hello2!");
      }
      function closeEventA() {
        bus.$off("myEvent1", eventA);
      }
      function closeEventB() {
        bus.$off("myEvent1", eventB);
      }
      function closeEventC() {
        bus.$off("myEvent2", eventC);
      }
      function closeEventD() {
        bus.$off("myEvent2", eventD);
      }
      function closeEventAll() {
        bus.$offs();
      }
    </script>
  </body>
</html>

界面如下:
在这里插入图片描述

点击按钮发布事件1:

在这里插入图片描述

点击按钮发布事件2:

在这里插入图片描述

点击按钮关闭all,然后再点击按钮发布事件1,这时候控制台没有输出。点击给A、B、C、D订阅事件,然后再点击按钮发布事件1

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值