原生js实现事件总线

/**
 * 发布-订阅模式
 * 自定义的事件总线
 * 方法: 
 * on: 绑定一个事件
 * once: 绑定一个一次性事件
 * off: 移除一个事件
 * emit: 触发一个事件
 * use: 添加一个中间件
 * 
 * @author chengxg
 * @since 2018-12-29
 * @constructor
 */
export function EventBus() {
  this.eventArr = []; //事件列表
  this.useFunArr = []; //添加的中间件列表
}

export default new EventBus() //默认导出一个实例

//事件模板
const eventTpl = {
  name: "", //事件名
  isOnce: false, //是否只执行一次
  //回调
  callback: function () {

  }
}
/**
 * 创建一个事件
 * @param {String} name 
 * @param {Function} callback 
 * @return {eventTpl}
 */
EventBus.prototype.createEvent = function (name, callback) {
  return {
    name: name, //事件名
    isOnce: false, //是否只执行一次
    callback: callback //回调
  }
}

/**
 * 获取事件
 * @param {String} name 
 * @param {Function} fn 
 * @return {eventTpl}
 */
EventBus.prototype.getEvent = function (name, fn) {
  let matchFn = fn && typeof fn == 'function';
  return this.eventArr.filter((e) => {
    let b = e.name === name;
    if (matchFn) {
      b = b && e.callback === fn;
    }
    return b;
  })
}

/**
 * 移除一个事件
 * @param {String} name 
 * @param {Function} fn fn为空则全部移除
 * @return {void}
 */
EventBus.prototype.removeEvent = function (name, fn) {
  let matchFn = fn && typeof fn == 'function';
  this.eventArr = this.eventArr.filter((e) => {
    let b = e.name === name;
    if (matchFn) {
      b = b && e.callback === fn;
    }
    return !b;
  })
}

/**
 * 移除一个事件, 同removeEvent
 * @param {String} name 
 * @param {Function} fn fn为空则全部移除
 * @return {void}
 */
EventBus.prototype.off = function (name, fn) {
  this.removeEvent(name, fn);
}

/**
 * 添加中间件
 * @param {function(string, object, ()=>{})} fn 中间件函数 fn(name, packet, next)
 * @return {void}
 */
EventBus.prototype.use = function (fn) {
  this.useFunArr.push(fn)
}

/**
 * 添加事件
 * @param {String} name 事件名
 * @param {Function} fn 执行的事件函数
 * @param {boolean} cover 是否覆盖之前的事件
 * @return {eventTpl}
 */
EventBus.prototype.on = function (name, fn, cover = false) {
  let ev = this.createEvent(name, fn);
  if (cover) {
    let eventArr = this.getEvent(name);
    if (eventArr.length > 0) {
      this.removeEvent(name);
    }
  }
  this.eventArr.push(ev);
  return ev;
}

/**
 * 添加事件, 执行完立即立即销毁
 * @param {String} name 事件名
 * @param {Function} fn 执行的事件函数
 * @param {boolean} cover 是否覆盖之前的事件
 * @return {void}
 */
EventBus.prototype.once = function (name, fn, cover = false) {
  let ev = this.on(name, fn, cover);
  ev.isOnce = true;
}

/**
 * 触发一个事件
 * 支持 通过中间件回调 next(newDate) 改变出入下一中间件的数据 
 * @param {String} name 事件名
 * @param {Object} data 传入事件监听方法的数据
 * @return {void}
 */
EventBus.prototype.emit = function (name, data) {
  //执行中间件
  let useFunArr = this.useFunArr;
  let useFuncLen = useFunArr.length;
  let index = 0;
  if (useFuncLen) {
    //从第一个中间件开始执行
    useFunArr[0](name, data, next);
    //执行过的中间件与中间件总数相比较
    if (index !== useFuncLen) {
      return;
    }
  }

  function next(newData) {
    //每执行一个中间件,指数+1
    index++;
    if (index < useFuncLen) {
      if (typeof newData !== 'undefined') {
        data = newData;
      }
      useFunArr[index](name, data, next);
    }
  }

  //触发函数
  let eventArr = this.getEvent(name);
  let len = eventArr.length,
    ev;
  for (let i = 0; i < len; i++) {
    ev = eventArr[i];
    //执行监听的事件
    if (typeof ev.callback === 'function') {
      let b = ev.callback(data);
      if (ev.isOnce) {
        this.removeEvent(ev.name, ev.callback);
      }
      if (typeof b != 'undefined' && b === false) {
        return;
      }
    }
  }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值