跳到主要内容

观察者模式

观察者任务

在开发过程中,常常需要监控某个目标是否需要执行自身的任务以及与该目标任务相关联的其他任务。Vue 框架便是使用观察者模式来监视 data 的变化,从而实现数据驱动的视图更新。

案例分析

假设有以下数据结构:

const userData = {
username: 'xxx',
age: 'xxx',
sex: 'xxx',
data: 'xxx',
};

任何一项数据的改变或访问,都可能需要记录日志。这时,数据的变化属于目标任务,而日志的打印和保存则是观察者任务

访问或修改 userData 中的任何属性时,观察者模式能够自动触发相应的日志记录操作,确保数据操作的可追溯性和系统的稳定性。

查看完整项目代码

实现 addEventListener

以下是一个简单的事件发布订阅(Observer)模式的实现,模拟 addEventListener 的功能:

class EventEmitter {
handlers = {};

// 订阅事件
on(eventType, callback, once = false) {
if (!this.handlers[eventType]) {
this.handlers[eventType] = [];
}

if (!this.handlers[eventType].includes(callback)) {
this.handlers[eventType].push({ callback, once });
}
}

// 订阅一次性事件
once(eventType, callback) {
this.on(eventType, callback, true);
}

// 取消订阅
off(eventType, callback) {
if (this.handlers[eventType]) {
this.handlers[eventType] = this.handlers[eventType].filter((handler) => handler.callback !== callback);
}
}

// 发布事件
emit(eventType, ...args) {
if (this.handlers[eventType]) {
this.handlers[eventType].forEach((handler) => {
handler.callback.apply(this, args);
if (handler.once) {
this.off(eventType, handler.callback);
}
});
}
}
}

const eventEmitter = new EventEmitter();

function handleClick() {
console.log('点击事件触发');
}

function handleHover() {
console.log('悬停事件触发');
}

function handleOnce() {
console.log('一次性事件触发');
}

eventEmitter.on('click', handleClick);
eventEmitter.on('hover', handleHover);
eventEmitter.once('click', handleOnce);

eventEmitter.emit('click');
// 输出:
// 点击事件触发
// 一次性事件触发

eventEmitter.emit('click');
// 输出:
// 点击事件触发

eventEmitter.emit('hover');
// 输出:
// 悬停事件触发

在上述代码中:

  • on 方法用于订阅事件,可以选择是否为一次性事件。
  • once 方法专门用于订阅一次性事件,触发后自动取消订阅。
  • off 方法用于取消订阅特定事件。
  • emit 方法用于发布事件,触发所有订阅该事件的回调函数。