当前位置:   article > 正文

JavaScript手写系列(二)———EventBus_js手写eventbus

js手写eventbus

前言

Vue中的组件传参是日常开发中常遇到的需求,其中EventBus事件总线就是其中非常好用的一种,之前其实是比较排斥这种用法的,就是因为用的少,不了解所以出于对未知事物的恐惧,比较排斥。最近刷到一篇手写EventBus的文章,看完才明白其中的大概原理,今天就以我自己的理解来给大家讲讲基本实现。

我们可以把EventBus简单理解为一个公众号,其中公众号作者拥有发布($emit)消息的能力,用户拥有订阅($on)公众号的能力,公众号作者发布文章后,用户会收到文章内容推送,如果用户不喜欢推送的文章则可以选择取消订阅($off)公众号的能力。接下来我们就来简单实现一下这些功能。

代码实现

function EventBus() {
  this.eventObj = {}; // 定义事件存储列表
  this.callbackId = 0; // 定义事件id  可以理解为公众号订阅者人数
}

// 订阅
EventBus.prototype.$on = function(key, callback) {
  if (this.eventObj[key] === undefined) {
    this.eventObj[key] = {}; // 如果不存在key的事件列表 则初始化为空  可以理解为 一个公众号可以有多个人订阅
  }
   const callbackIndex = this.callbackId++; // 先赋值再添加 每添加一个订阅者 人数加1
  this.eventObj[key][callbackIndex] = callback; //将回调函数添加到事件列表中 可以理解为添加订阅公众号人数,并为每个订阅者提供通知服务
  return callbackIndex; // 返回订阅者id 可以理解为是第几个订阅的人
};

// 发布
EventBus.prototype.$emit = function(key, ...args) {
  const EventList = this.eventObj[key]; // 获取本次发布内容对应的所有订阅者
  Object.keys(EventList).forEach((fnKey) => {
    EventList[fnKey](...args); // 执行传入的函数  可以理解为挨个通知所有订阅者本次发布的内容
    if (fnKey.indexOf("once") > -1) {
      // 只执行一次的订阅 执行完就删除
      delete EventList[fnKey];
    }
  });
};

// 取消
EventBus.prototype.$off = function(key, id) {
  delete this.eventObj[key][id]; // 删除订阅事件 可以理解为取消通知订阅者
  if (this.eventObj[key].length === 0) {
    // 如果没人关注公众号 就删除该事件
    delete this.eventObj[key];
  }
};

// 执行一次
EventBus.prototype.$once = function(key, callback) {
  if (this.eventObj[key] === undefined) {
    // 未订阅过该事件
    this.eventObj[key] = {};
  }
  const callbackIndex = this.callbackId++; // 先赋值再添加 每添加一个订阅者 人数加1
  this.eventObj[key]["once" + callbackIndex] = callback; //将回调函数添加到事件列表中 可以理解为添加订阅公众号人数,并为每个订阅者提供通知服务,使用once标记只订阅一条消息的订阅者
  return callbackIndex; // 返回订阅者id 可以理解为是第几个订阅的人
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

代码验证

接下来我们通过几个例子来验证这几个实现的功能。
1.发布、订阅

const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});
eventBus.$emit("gongzhonghao1", "文章内容1");
eventBus.$emit("gongzhonghao1", "文章内容2");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

公众号发布了两次消息,两个用户都收到了两条消息。
在这里插入图片描述

取消订阅

const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
const id = eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});

eventBus.$emit("gongzhonghao1", "文章内容1");

eventBus.$off('gongzhonghao1', id)  

eventBus.$emit("gongzhonghao1", "文章内容2");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在发布第二条消息之前取消了订阅公众号 所以用户2只收到了公众号1发布的第一条内容
在这里插入图片描述

3.订阅一次


const eventBus = new EventBus();

eventBus.$on("gongzhonghao1", (content) => {
  console.log(`用户1订阅了gongzhonghao1,${content}`);
});
 eventBus.$once("gongzhonghao1", (content) => {
  console.log(`用户2订阅了gongzhonghao1,${content}`);
});

eventBus.$emit("gongzhonghao1", "文章内容1");


eventBus.$emit("gongzhonghao1", "文章内容2");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

用户2只订阅了一次内容,所以无法收到第二条消息

在这里插入图片描述

参考文章

# 面试官:请手写一个EventBus,让我看看你的代码能力!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/628273
推荐阅读
相关标签
  

闽ICP备14008679号