🤍 前端开发工程师、技术日更博主、已过CET6
🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1
🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》
🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》
💬 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
on
(用于订阅事件)
off
(用于取消订阅事件)
once
(用于订阅只执行一次的事件)
以下是使用JavaScript实现一个简单的观察者模式,包含on
(用于订阅事件)、off
(用于取消订阅事件)、once
(用于订阅只执行一次的事件)方法的示例代码,观察者模式可以方便地实现对象间的一对多依赖关系,使得当一个对象状态改变时,其依赖对象会收到通知并自动更新。
// 定义一个事件中心类,用于管理事件的订阅、发布等操作
class EventEmitter {
constructor() {
// 用于存储不同事件类型对应的回调函数列表
this.events = {};
}
// on方法用于订阅事件,接收事件名称和回调函数作为参数
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
// off方法用于取消订阅事件,可根据事件名称和具体的回调函数来取消指定的订阅
off(eventName, callback) {
if (this.events[eventName]) {
const index = this.events[eventName].indexOf(callback);
if (index!== -1) {
this.events[eventName].splice(index, 1);
}
// 如果该事件对应的回调函数列表为空了,删除这个事件类型的记录
if (this.events[eventName].length === 0) {
delete this.events[eventName];
}
}
}
// once方法用于订阅只执行一次的事件,内部借助on方法和一个标记函数来实现
once(eventName, callback) {
const onceCallback = (...args) => {
callback(...args);
this.off(eventName, onceCallback);
};
this.on(eventName, onceCallback);
}
// emit方法用于触发事件,接收事件名称以及可选的参数,会依次执行该事件对应的所有回调函数
emit(eventName,...args) {
if (this.events[eventName]) {
this.events[eventName].forEach(callback => callback(...args));
}
}
}
// 使用示例
const eventEmitter = new EventEmitter();
// 订阅事件 'event1'
const callback1 = (data) => {
console.log('事件1触发,收到数据:', data);
};
eventEmitter.on('event1', callback1);
// 订阅只执行一次的事件 'event2'
const callback2 = (data) => {
console.log('一次性事件2触发,收到数据:', data);
};
eventEmitter.once('event2', callback2);
// 触发 'event1' 事件
eventEmitter.emit('event1', '来自事件1的消息');
// 再次触发 'event1' 事件,依然会执行对应的回调函数
eventEmitter.emit('event1', '又一次来自事件1的消息');
// 触发 'event2' 事件,只会执行一次对应的回调函数
eventEmitter.emit('event2', '来自一次性事件2的消息');
// 再次触发 'event2' 事件,由于已经取消订阅,不会执行回调函数了
// 取消订阅 'event1' 中的 callback1
eventEmitter.off('event1', callback1);
// 再次触发 'event1' 事件,因为已经取消订阅,所以不会执行任何回调函数了
eventEmitter.emit('event1', '这是取消订阅后触发的消息');
在上述代码中:
-
EventEmitter
类结构及功能constructor
:构造函数中初始化了一个空对象this.events
,用于存储不同事件对应的回调函数列表。例如,'event1'
事件对应的回调函数都会存储在this.events['event1']
数组中。on
方法:首先判断对应事件名称的回调函数列表是否已存在,如果不存在则创建一个空数组。然后将传入的回调函数添加到对应事件的回调函数列表中,这样后续当该事件被触发时,所有添加的回调函数都会被执行。off
方法:针对指定的事件名称和回调函数,先查找该回调函数在对应列表中的索引,如果能找到(索引不为-1
),则从列表中删除这个回调函数。并且如果该事件的回调函数列表为空了,就从this.events
中删除这个事件的记录,释放内存。once
方法:创建一个新的内部回调函数onceCallback
,在这个函数内部先执行传入的原始回调函数callback
,然后立即调用off
方法取消对该事件的这次订阅,从而实现只执行一次的效果。之后将这个内部回调函数添加到对应事件的订阅列表中,借助已有的on
方法实现功能。emit
方法:根据传入的事件名称查找对应的回调函数列表,如果存在,则遍历列表,依次执行每个回调函数,并将额外传入的参数传递给这些回调函数,实现通知所有订阅者的功能。
-
使用示例说明
- 首先创建了
EventEmitter
实例eventEmitter
,然后通过on
方法订阅了'event1'
事件,对应的回调函数callback1
会在'event1'
每次触发时被执行。 - 接着使用
once
方法订阅了'event2'
事件,对应的回调函数callback2
只会在'event2'
首次触发时执行,之后就自动取消订阅了。 - 通过多次调用
emit
方法来触发不同的事件,展示了订阅、取消订阅以及一次性订阅的实际效果,验证了各个方法的功能是否符合预期。
- 首先创建了
这样实现的观察者模式可以灵活应用在很多场景中,比如DOM事件处理、组件间通信等,方便地管理不同对象之间的依赖关系和消息通知机制。你可以根据实际需求进一步扩展和优化这个代码,例如添加事件类型的合法性检查、对更多参数的处理等功能。