美文网首页
js-发布订阅模式实现EventBus

js-发布订阅模式实现EventBus

作者: _stan | 来源:发表于2021-06-07 00:07 被阅读0次

    Vue2.x中兄弟组件之间传值可以使用Vuex来达到目的,如果项目中不需要类似Vuex这样的库来处理组件之间的数据通信,就可以考虑Vue中的事件总线 ,即 EventBus来通信。

    vue2.x中实现实现EventBus
    // event-bus.js
    import Vue from 'vue'
    export const EventBus = new Vue()
    
    或者
    
    // main.js
    Vue.prototype.$EventBus = new Vue()
    

    因为vue实例中提供了$on、$emit等方法所以只需要创建一个空的vue实例,在组件中通过$on()注册事件,在另外一个组件中通过$emit()去执行对应的事件并且可以传参来达到组件之间的通讯。

    实现一个简单的EventBus
    const eventBus = () => {
      /* 订阅器 */
      subs = new Map();
    
      return {
        subs,
    
        /**
          * 注册事件
          * @param {string} type 事件类型
          * @param {Function} callback 回调函数 
          */
        $on (type, callback) {
          const sub = subs.get(type);
          const isEmpty = sub && sub.push(callback);
          if (!isEmpty) {
            subs.set(type, [callback]);
          }
        },
    
        /**
          * 触发事件
          * @param {string} type 事件类型
          * @param {Any} payload 传递的参数
          */
        $emit (type, ...payload) {
          (subs.get(type) || []).forEach(fn => { fn(...payload) });
          (subs.get('*') || []).forEach(fn => { fn(...payload) }); /* 所有事件类型都执行 */
        },
        
        /**
          * 注销事件
          * @param {string} type 事件类型
          * @param {Function} callback 回调函数 
          */
        $off (type, callback) {
          const sub = subs.get(type);
          if (sub) {
            sub.splice(sub.indexOf(callback) >>> 0, 1);
          }
        }
      }
    }
    
    module.exports = eventBus
    

    subs订阅器可以使用对象或者来Map来实现,Map自带clear方法可以清除所有注册的事件

    subs = new Map();
    

    其原理就是以事件类型type作为Map的key值,以数组作为value值,数组里面装的是一个个执行的回调函数,通过$on注册的事件如果是相同的type就会被push同一个数组当中,调用$emit的时候找到对应的type循环数组执行里面所有的回调函数。

    使用
    const eventBus = require('./eventBus')
    const emitter = eventBus()
    
    // 注册change事件
    emitter.$on('change', (...payload) => {
      console.log('change', ...payload)
    })
    
    // 调用所有事件都会执行这个方法
    emitter.$on('*', (...payload) => {
      console.log('all', ...payload)
    })
    
    //触发change事件
    emitter.$emit('change', '参数1', '参数2')
    
    运行结果
    image

    可以使用Map自带的clear清空EventBus

    emitter.subs.clear() // 清空EventBus
    

    相关文章

      网友评论

          本文标题:js-发布订阅模式实现EventBus

          本文链接:https://www.haomeiwen.com/subject/alsteltx.html