赞
踩
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.发布、订阅
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");
公众号发布了两次消息,两个用户都收到了两条消息。
取消订阅
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");
在发布第二条消息之前取消了订阅公众号 所以用户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");
用户2只订阅了一次内容,所以无法收到第二条消息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。