本文的代码仅针对vue使用
一、eventbus介绍
eventbus就是数据总线,全局通信的一种方案。 很多语言都有这个东西。
二、基本使用
1.普通版
import Vue from 'vue'
export default new Vue()
2.二次封装一下
import Vue from 'vue';
class EventBus {
constructor() {
this.bus = new Vue();
this.events = new Set();
}
$on(eventName, callback) {
// 如果同名事件已存在,则卸载上一个同名称事件
if (this.events.has(eventName)) {
this.$off(eventName);
}
setTimeout(() => {
this.events.add(eventName)
this.bus.$on(eventName, callback);
}, 0)
}
$emit(eventName, ...args) {
this.bus.$emit(eventName, ...args);
}
$off(eventName) {
if (this.events.has(eventName)) {
this.events.delete(eventName)
}
this.bus.$off(eventName);
}
}
export default new EventBus();
settimeout 是重点, 放到异步队列去订阅,有效避免重复发布订阅不到的问题。
三、使用
1.先引入
import eventBus from "@/utils/eventBus";
2.发布
eventBus.$on('eventName', (value) => {
console.log(value)
})
3.订阅
eventBus.$emit('eventName', {})
4.卸载
eventBus.$off('eventName')
5.关键
- 在组件A我们发布了一个事件, 组件A卸载的时候我们要手动把发布的事件一起卸载了。
- 事件名是个字符串,不要起重复的名字,这玩意没命名空间,会覆盖。
- vue2用用就得了,有vuex都不要用这个。vue3更没必要用,有pinia,体积又不大,用起来还很香。
总结
我的看法是这个东西看似好像很好用,随便哪里都能通信,代码写的还不多,好理解。 实际除非你的项目很小,需要全局维护的地方不多,用这个图个快捷方便。使用问题还是多多,重复发布相同名称的事件就有bug了,发布了不卸载,就内存泄露了。项目中用的多了,就难以维护了。
吐槽:我目前面对的问题是,接手了一个项目,总是会内存溢出。我就去通过开发者工具去排查,发现这个内存总是下不来。先检查一波定时器之类的,又检查了一遍一些包,有没有在指定时机卸载,发现一些点,修正后,还是存在明显的内存泄露问题。很严重,长时间操作浏览器会内存不足崩溃那种。这个时候我发现项目中使用了eventbus。全局一搜索,500多处使用,后面我利用我二次封装的代码,在$on里打印仅仅刚进入应用就将近发布了二十几个。 我的内心是崩溃的,让我一个个去追踪,我是拒绝的。只能想办法根源处处理一下,所以我二次封装了一下。这波是前人乘凉,后人栽树。