js中订阅发布模式bus

export default {
  list: {}, // 事件中心集中地
  /**
   * 发布订阅
   * @param {string} name 事件名
   * @param  [...args]
   */
  $emit: function (name) {
    if (this.list[name]) {
      for (let i = 0; i < this.list[name].length; i++) {
        this.list[name][i].apply(this, Array.from(arguments).slice(1));
      }
    }
  },
  /**
   * 订阅一次后取消订阅
   * @param {string} name 事件名
   * @param {*} fn
   */
  $once: function (name, fn) {
    function on() {
      // 触发一次后移除
      fn.apply(this, arguments);
      this.$off(name, on);
    }
    // 加个标识,如一次都没触发的时候也可以手动移除订阅
    on.fn = fn;
    this.$on(name, on);
  },
  /**
   * 订阅
   * @param {string|Array<strig>} name 事件名
   * @param {Function} fn
   * @returns
   */
  $on: function (name, fn) {
    // 传入的数组循环调用订阅
    if (Array.isArray(name)) {
      for (let i = 0; i < name.length; i++) {
        this.$on(name[i], fn);
      }
      return;
    }
    if (this.list[name]) {
      this.list[name].push(fn);
    } else {
      this.list[name] = [fn];
    }
  },
  /**
   * 取消订阅
   * @param {string|Array<string>|null} name 事件名
   * @param {Function|null} fn
   * @returns
   */
  $off: function (name, fn) {
    // 没传入参数,清空所有订阅
    if (!name) {
      this.list = {};
      return;
    }
    if (Array.isArray(name)) {
      for (let i = 0; i < name.length; i++) {
        this.$off(name[i], fn);
      }
      return;
    }
    const cbs = this.list[name];
    // 没有订阅,直接返回
    if (!cbs) return;
    // 没有传入对应的订阅,清空所有相关订阅
    if (!fn) {
      this.list[name] = null;
      return;
    }
    // 找到对应的订阅删除
    for (let i = 0; i < cbs.length; i++) {
      if (cbs[i] === fn || cbs[i].fn === fn) {
        cbs.splice(i, 1);
        break;
      }
    }
  }
};

event 用法
$on $on(evnet,callback), $on([evnet,evnet2],callback)
$off $off(), $off(event), $off(event,callback)
$once $once(evnet,callback)
$emit $emit(event), $emit(event,[...args])

html中使用

// 引入
<script type="module">
import bus from './bus.js';
// 挂载到window上
window.$bus = bus;
</script>
<script>
// 用法
// window.$bus.$on(event,callback), 订阅
// window.$bus.$once(event,callback), 订阅一次后移除订阅
// window.$bus.$off(event,callback), 移除订阅
// window.$bus.$emit(event,[...args]), 发布
</script>

vue2中使用

// main.js中引入
import bus from './bus.js';
// 挂在到原型上,创建事件总线
Vue.prototype.$bus = bus;

// 用法
// this.$bus.$on(event,callback), 订阅
// this.$bus.$once(event,callback), 订阅一次后移除订阅
// this.$bus.$off(event,callback), 移除订阅
// this.$bus.$emit(event,[...args]), 发布
posted @ 2022-06-28 15:31  萝卜爱吃肉  阅读(265)  评论(0编辑  收藏  举报