自定义实现一个事件触发器EventEmitter

2019-06-07  本文已影响0人  xiabenglakaA

前言,闲来没事实现一个事件触发器,此代码仅供参考。
假如屏幕前的你要拿来用则存在两个问题需要提前知道
1、代码中使用了es6的东西 在浏览器里可能会不兼容
2、Event 与浏览器中的全局Event冲突了 使用会造成不可预料的问题。

function Event() {
  // 存所有事件名字的
  this.eventNames = {
    // "click":[],
  };
}
((p) => {
  // 检查事件名
  function eventNameCheck(eventName) {
    if (typeof eventName !== 'string') {
      throw TypeError('事件名必须使用字符串类型');
    }
  }
  // 检查事件监听函数
  function handleCheck(handle) {
    if (typeof handle !== 'function') {
      throw TypeError('事件监听 handle必须是一个函数');
    }
  }
  // 添加事件
  function addHandle(eventName, handle) {
    if (!this.eventNames[eventName]) {
      this.eventNames[eventName] = [];
    }
    this.eventNames[eventName].push(handle);
  }

  // 监听事件
  p.on = function on(eventName, handle) { // eslint-disable-line
    eventNameCheck(eventName);
    handleCheck(handle);
    addHandle.call(this, eventName, handle);
  };
  // 一次事件 事件执行一次即被删除
  p.once = function once(eventName, handle) { // eslint-disable-line
    eventNameCheck(eventName);
    handleCheck(handle);
    const that = this;
    const newHandle = function newHandle(data) {
      handle(data);
      that.remove(eventName, newHandle);
    };
    addHandle.call(this, eventName, newHandle);
  };
  // 派发事事件
  p.emit = function emit(eventName, data) { // eslint-disable-line
    eventNameCheck(eventName);
    // 如果有eventName事件的兼听函数
    if (this.eventNames[eventName]) {
      const oldEventName = this.eventNames[eventName];

      oldEventName.forEach((handle) => {
        handle(data);
      });
    }
  };
  // 移除事件
  p.remove = function remove(eventName, handle) { // eslint-disable-line
    eventNameCheck(eventName);
    handleCheck(handle);
    const oldEventName = this.eventNames[eventName];
    if (oldEventName) {
      let index;
      this.eventNames[eventName].forEach((newHandle, newIndex) => {
        if (newHandle === handle) {
          index = newIndex;
        }
      });
      if (index != undefined) { // eslint-disable-line
        oldEventName.splice(index, 1);
        // 移除一个事件回调函数后如果此事件已没有其它回调函数,则将当前事件清空,已节省内存
        if (!oldEventName.length) {
          this.eventNames[eventName] = null;
        }
        return true;
      }

      return false;
    }

    throw Error(`没有监听的[${eventName}]事件`);
  };
  // 移除所有事件
  p.removeAll = function removeAll(eventName) { // eslint-disable-line
    if (eventName) {
      eventNameCheck(eventName);
      const oldEventName = this.eventNames[eventName];
      if (oldEventName) {
        this.eventNames[eventName] = null;
        return true;
      }

      return false;
    }
    // 如果没有传事件名字,则清空所有事件

    this.eventNames = {};
    return true;
  };
})(Event.prototype);

export default new Event();

上一篇下一篇

猜你喜欢

热点阅读