bus.js 1.69 KB
import Vue from "vue";
// 存储所有的事件
const EventStore = {};
const Bus = new Vue();

// 存放当前组件实例
const destoryHandler = function () {
  // this 为调用此方法的vue组件
  const currentEventObj = EventStore[this._uid];
  if (!currentEventObj) {
    return;
  }
  for (const type in currentEventObj) {
    const key = Array.isArray(type) ? type.join(",") : type;
    // Bus 解绑事件
    Bus.$off(type, currentEventObj[key]);
  }
  // 删除记录的事件集合
  delete EventStore[this._uid];
};

const BusFactory = (vm) => {
  // 获取当前组件实例的destroyed生命周期
  const destroyed = vm.$options.destroyed;
  // 获取当前组件实例的uid
  const uid = vm._uid;
  // 不存在则声明一个对象,防止每次只存最后一个
  if (!Object.prototype.hasOwnProperty.call(EventStore, uid)) {
    EventStore[uid] = {};
  }
  !destroyed.includes(destoryHandler) && destroyed.push(destoryHandler);
  return {
    $on: (type, handler) => {
      const key = Array.isArray(type) ? type.join(",") : type;
      EventStore[uid][key] = handler;
      Bus.$on(type, handler);
    },
    $off: (type, handler) => {
      if (!type) {
        delete EventStore[uid];
        Bus.$off();
        return;
      }
      const key = Array.isArray(type) ? type.join(",") : type;
      // 删除对应的事件
      delete EventStore[uid][key];
      Bus.$off(type, handler);
    },
    $once: (...params) => Bus.$once(...params),
    $emit: (...params) => Bus.$emit(...params),
  };
};

// 这两行是允许bus不调用依然能够触发emit和once
BusFactory.$emit = (...params) => Bus.$emit(...params);
BusFactory.$once = (...params) => Bus.$once(...params);

export default BusFactory;