EventBus
Event Bus 事件总线实际上就是创建一个基于发布-订阅模式(Publish/Subscribe)的对象,它可以帮助我们在不同组件或模块之间进行通信。
极简实现
js
// 创建一个 EventBus 类
class EventBus {
constructor() {
// 初始化一个空对象来存储事件及其对应的处理器函数
this.events = {};
}
// 订阅(注册)事件
on(eventName, callback) {
// 如果该事件还未被订阅过,则创建一个新的回调函数数组
if (!this.events[eventName]) {
this.events[eventName] = [];
}
// 将回调函数添加到事件对应的处理器数组中
this.events[eventName].push(callback);
}
// 取消订阅事件
off(eventName, callback) {
if (this.events[eventName]) {
// 从事件的处理器数组中移除指定的回调函数
this.events[eventName] = this.events[eventName].filter(
(cb) => cb !== callback
);
}
}
// 发布(触发)事件,并传递可选数据给回调函数
emit(eventName, ...data) {
// 如果存在该事件以及其相关的处理器函数
if (this.events[eventName]) {
// 遍历并执行所有订阅了该事件的回调函数
this.events[eventName].forEach((callback) => callback.apply(this, data));
}
}
// 添加一次性订阅方法(只会执行一次)
once(eventName, callback) {
const onceCallback = (...args) => {
this.off(eventName, onceCallback);
callback.apply(this, args);
};
this.on(eventName, onceCallback);
}
}
// 使用示例:
const bus = new EventBus();
// 订阅事件
bus.on("myEvent", function (message) {
console.log("Received:", message);
});
// 发布事件
bus.emit("myEvent", { message: "Hello from EventBus!" });
// 一次性订阅
bus.once("oneTimeEvent", function (data) {
console.log("Fired only once with:", data);
});
// 发布一次性事件
bus.emit("oneTimeEvent", { message: "This will be logged just once." });
更完整的实现
js
class EventBus {
constructor() {
this.events = {};
}
/**
* 订阅事件
* @param {string} eventName - 事件名称
* @param {Function} callback - 事件处理器函数
* @param {boolean} [once=false] - 是否只订阅一次
*/
on(eventName, callback, once = false) {
if (!eventName || typeof callback !== "function") {
throw new Error('Invalid arguments for "on" method');
}
let callbacks = this.events[eventName];
if (!callbacks) {
callbacks = this.events[eventName] = [];
}
if (once) {
const onceWrapper = (...args) => {
callback.apply(this, args);
this.off(eventName, onceWrapper);
};
callbacks.push(onceWrapper);
} else {
callbacks.push(callback);
}
}
/**
* 取消订阅事件
* @param {string} eventName - 事件名称
* @param {Function} [callback] - 要取消的特定处理器函数,不传则取消该事件的所有订阅
*/
off(eventName, callback) {
if (!eventName) {
throw new Error('Invalid argument for "off" method');
}
const callbacks = this.events[eventName];
if (!callbacks) return;
if (callback) {
this.events[eventName] = callbacks.filter((cb) => cb !== callback);
} else {
delete this.events[eventName];
}
}
/**
* 发布(触发)事件
* @param {string} eventName - 事件名称
* @param {...*} args - 传递给回调函数的参数列表
*/
emit(eventName, ...args) {
if (!eventName) {
throw new Error('Invalid argument for "emit" method');
}
const callbacks = this.events[eventName];
if (callbacks) {
callbacks.forEach((cb) => cb.apply(this, args));
}
}
}
// 使用示例:
const bus = new EventBus();
// 订阅事件
bus.on("myEvent", function (a, b, c) {
console.log("Received:", a, b, c);
});
// 发布事件,传递多个参数
bus.emit("myEvent", "Hello", "from", "EventBus!");
// 一次性订阅
bus.on(
"oneTimeEvent",
function (data) {
console.log("Fired only once with:", data);
},
true
);
// 发布一次性事件
bus.emit("oneTimeEvent", { message: "This will be logged just once." });