请使用javascript实现一个EventMitter类

103 阅读2分钟

EventEmitter 类实现

在 JavaScript 中,事件驱动编程是一个常见的模式。实现一个简单的 EventEmitter 类可以帮助我们管理和触发事件。以下是一个完整的 EventEmitter 类的实现,包括事件的注册、注销和触发。

代码实现

class EventEmitter {
  constructor() {
    this.events = {}; // 存储事件及其监听函数
  }

  // 注册事件
  on(event, listener) {
    if (!this.events[event]) {
      this.events[event] = []; // 初始化事件数组
    }
    this.events[event].push(listener); // 添加监听函数到事件数组
  }

  // 解除事件注册
  off(event, listener) {
    if (!this.events[event]) return; // 如果没有该事件,直接返回
    this.events[event] = this.events[event].filter(l => l !== listener); // 过滤掉指定的监听函数
  }

  // 触发事件
  emit(event, ...args) {
    if (!this.events[event]) return; // 如果没有该事件,直接返回
    this.events[event].forEach(listener => listener(...args)); // 调用所有监听函数并传递参数
  }

  // 只执行一次的事件
  once(event, listener) {
    const wrapper = (...args) => {
      listener(...args); // 调用监听函数
      this.off(event, wrapper); // 调用后自动解除注册
    };
    this.on(event, wrapper); // 注册包装的监听函数
  }
}

使用示例

以下是如何使用 EventEmitter 类的示例。

const emitter = new EventEmitter();

// 注册事件
const onMessage = (message) => {
  console.log(`收到消息: ${message}`);
};

emitter.on('message', onMessage);

// 触发事件
emitter.emit('message', 'Hello, World!'); // 输出: 收到消息: Hello, World!

// 解除事件注册
emitter.off('message', onMessage);
emitter.emit('message', '你不会看到这个消息'); // 无输出

// 注册一次性事件
emitter.once('onceEvent', (data) => {
  console.log(`一次性事件: ${data}`);
});

emitter.emit('onceEvent', '第一次触发'); // 输出: 一次性事件: 第一次触发
emitter.emit('onceEvent', '第二次触发'); // 无输出

代码说明

  1. 构造函数:初始化一个空的对象 events 用于存储事件及其对应的监听函数。
  2. on 方法:用于注册事件监听器,检查事件是否已经存在,如果不存在则初始化为一个空数组,然后将监听器推入该数组。
  3. off 方法:用于解除事件监听器,检查事件是否存在,如果存在则使用 filter 方法过滤出不与指定监听器相等的函数,达到解除的效果。
  4. emit 方法:用于触发事件,检查事件是否存在,如果存在则遍历所有注册的监听器并调用它们,同时将参数传递给它们。
  5. once 方法:用于注册一次性事件,内部创建一个包装函数,在执行后自动解除注册。

注意事项

  • 事件名可以是任意字符串,确保在使用时保持一致。
  • 监听函数的参数可以根据实际需要传递。
  • off 方法解除监听器时需确保要解除的函数是正确的引用,如果使用匿名函数则无法正确解除。

总结

通过实现一个简单的 EventEmitter 类,我们可以轻松地管理事件的注册、触发和解除。这样的结构在大型应用中非常有用,可以有效地解耦模块之间的交互,提高代码的可维护性和可读性。