什么是EventBus?其实就是事件的订阅与发布,广泛用于页面之间的传值,原理:

举个简单的例子,一个发布者可以被多次订阅,当发布者的数据改变时,那么订阅者也会实时做出改变;

优势:

  • 简化了组件间的通讯。
  • 分离了事件的发送者和接受者。
  • 避免了复杂的和易错的依赖关系和生命周期问题。
  • 使得代码更简洁,性能更好。

具体应用场景:

以小程序为例,假如有一个电商网站,用户下单时肯定要选择自己的收货地址,那么进入子页面选择好收货地址后,页面自动返回上一级订单页面,这时候订单页显示的收货地址应该是用户在子页面中所选择的地址,如果保存在全局变量中或缓存中,会不会随着业务逻辑的增多而变得混乱不堪?这时候EventBus事件订阅就显得异常简洁;

直接上代码,首先在工具类中新建一个js文件,就叫event.js:

const events = {};

const on = (name, self, callback) => {
  let tuple = [self, callback];
  let callbacks = events[name];
  if (Array.isArray(callbacks)) {
    callbacks.push(tuple);
  }
  else {
    events[name] = [tuple];
  }
}

const remove = (name, self) => {
  let callbacks = events[name];
  if (Array.isArray(callbacks)) {
    events[name] = callbacks.filter((tuple) => {
      return tuple[0] != self;
    })
  }
}

const emit = (name, data) => {
  let callbacks = events[name];
  if (Array.isArray(callbacks)) {
    callbacks.map((tuple) => {
      let self = tuple[0];
      let callback = tuple[1];
      callback.call(self, data);
    })
  }
}

module.exports = {
  on:on,
  remove:remove,
  emit:emit,
};

假如在小程序中,有一个首页,每点击一次红色的块,数字就+1,同时,个人中心页面的数字也要和首页保持同步(即首页的数字变化后,要传递给个人中心页面)

先看看首页的js写法,在页面之前引入event.js:

const app = getApp();
const event = app.requirejs('event');

data部分为:

  /**
   * 页面的初始数据
   */
  data: {
    num: 1,
  },

方法为:

  getNum() {
    let newNum = this.data.num;
    newNum++;
    this.setData({
      num: newNum,
    });
    event.emit('DataChanged', newNum);
  },

可以看出,每点击首页的块一次,那么就将生成的newNum发布为‘DataChanged’这个事件,那么个人中心页面该如何接收呢?

  watchData() {
    event.on('DataChanged', this, (res) => {
      this.setData({
        num: res,
      });
    });
  },

在生命周期onLoad()中,直接调用watchData()方法即可,需要注意的是,在onUnload时,需要将’DataChanged’事件移除,以免造成内存泄漏。

在个人中心页面定义一个watchData方法,接收’DataChanged’事件,并将接收到的结果更新至num中。

使用EventBus还需要注意到的一个坑是,事件发布与订阅的页面,都必须是激活状态,也就是被用户点击过的页面,否则无法使用!