手写一个发布订阅

234 阅读2分钟

在umi搭建的框架中使用

通过引入import { EventEmitter } from 'events';方法处理通知事件 EventEmitter是一个类方法,需要初始化构造函数后使用其内的方法

pageA 发送通知事件

import { EventEmitter } from 'events
const events = new EventEmitter();

// 发送通知事件
// 参数1:通知事件名
// 参数2:传递给该事件的参数
events.emit('通知事件名', '我是一条新消息');

pageB接收通知事件

import { EventEmitter } from 'events
const events = new EventEmitter();

const handleMessage = (message) => {
  console.log(message)
}

// 事件监听统一写入页面初始化事件,且只需要执行一次
useEffect(() => {
  // 参数为监听的事件名称,事件参数
  events.addListener('通知事件名', handleMessage);

  return () => {
    // 页面注销时需要销毁此事件的监听
    events.removeListener('通知事件名', handleMessage);
  }
}, []);

完整使用

由于每次使用都需要new EventEmitter()方法,我们可以对其进行统一处理,在一处new完后将实例导出使用

// utils
import { EventEmitter } from 'events
const events = new EventEmitter();
export default events;

// page
import { events } from '@/utils';

// 在此处监听名为sendMessage的事件
events.emit('sendMessage', '我是一条新消息');

events.addListener('sendMessage', handleMessage);
events.removeListener("sendMessage", handleMessage);
  }

在react-native中使用

中事件监听时使用native中的插件DeviceEventEmitter来实现 import { DeviceEventEmitter } from 'react-native';

发送事件

import { DeviceEventEmitter } from 'react-native';

DeviceEventEmitter.emit('通知名称', '我是参数')

监听事件

useEffect(() => {
  const listener = DeviceEventEmitter.addListener('通知名称', (message) => {
    console.log(message);  //监听
  })

  return () => {
    // 页面销毁时,删除此页面对应的所有监听
   listener.remove();
  }
}, []);

在Taro中使用监听

Taro自带apieventCenter可以进行事件监听与发送

监听事件on

Taro.eventCenter.on('sendMessage', handleMessage);

销毁事件off

Taro.eventCenter.off('sendMessage', handleMessage);

通知触发事件trigger

Taro.eventCenter.trigger('sendMessage', {message: '我是参数'});

手写一个发布订阅者模式

下面代码实现了一个基本的事件总线

class EventEmitter {
  constructor() {
    // 记录所有需要监听的方法
    this.cache = {};
  }

  /**
   * 监听一个事件
   * @param {*} name 监听事件名称
   * @param {*} fun 需要监听的事件方法
   */
  on = (name, fun) => {
    const tasks = this.cache[name];
    if (tasks) {
      // 需要监听的方法已存在
      if (!tasks.some(fn => fn === fun)) return;

      tasks.push(fun);
    } else {
      this.cache[name] = [fun];
    }
  }

  /**
   * 销毁监听
   * @param {*} name 监听事件名称
   * @param {*} fun 监听事件方法
   */
  off = (name, fun) => {
    const tasks = this.cache[name];
    if (!tasks) return;

    const index = tasks.findIndex(f => f === fun || f.callback === fun);
    if (index === -1) return;

    tasks.splice(index, 1);

    // 当前name不存在数据时删除当前name字段
    if (!this.cache[name].length) { 
      delete this.cache[name];
    }
  }

  /**
   * 触发监听事件
   * @param {*} name 监听事件名称
   * @param  {...any} args 
   */
  emit = (name, ...args) => {
    const tasks = this.cache[name];
    if (!tasks) return;

    for (const fun of tasks) {
      fun(...args);
    }
  }
}

const eventEmitter = new EventEmitter();

export default eventEmitter;

调用方式

import eventEmitter from '/eventEmitter';

eventEmitter.emit('updateData', '我是参数');
eventEmitter.on('updateData', updateData);
eventEmitter.off('updateData', updateData);
function updateData() {}