- 归纳:
简单来说就是通过对象这种key,value的映射特性把一个我们未来可能会用到的事件类型和对应事件先注册到一个全局的对象中,这一步也叫做订阅,就是我们的on事件,然后再在其他地方去触发这个事件,这一步也叫做发布,对应我们的emit事件,发布的时候可以携带参数,从而触发我们订阅的这个事件,这个被订阅的事件被触发并且接受到触发时候携带的参数。 - 通常应用的场景:
页面之间的通信,比如在A页面订阅一个事件,在B页面去发布这个事件并且携带参数,A页面的事件被触发拿到B页面发布时携带的参数,从而达到组件之间的通讯;
import React from "react";
const GlobleEvents = function () {
const events = {};
// 订阅
this.on = function (type, handler) {
// hanlder 必须是一个函数,如果不是直接报错
if (!(handler instanceof Function)) {
throw new Error("哥 你错了 请传一个函数")
}
// 判断 type 事件对应的队列是否存在
if (!this.eventMap[type]) {
// 若不存在,新建该队列
this.eventMap[type] = []
}
// 若存在,直接往队列里推入 handler
this.eventMap[type].push(handler)
};
// 发布
this.emit = function (type, params) {
if (events[type]) {
events[type].forEach(func => {
func(params)
})
}
};
// 补充(解除监听)
this.off = function (type, handler) {
if (this.eventMap[type]) {
this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1)
}
}
}
window.globleEvents = new GlobleEvents();
const A = () => {
const handleChange = (params) => {
console.log('params', params)
}
return <div onClick={() => {
globleEvents.on('test', handleChange);
}}>订阅</div>
}
const B = () => {
return <div>
<div onClick={() => {
globleEvents.emit('test', '我是一个属于B的参数');
}}>发布</div>
<A />
</div>
}
export default B;
补充:
还有一个常用的使用场景:
多个不同的模块都需要用到某些公众的数据,但是每个模块处理这个数据的的方法都是不同的。这种场景可以使用发布订阅者模式。
$.ajax('url',function(data){
globleEvents.emit('handle', data); //获取到数据后发布
})
组件中的订阅:
A组件:
globleEvents.on('handle', function(data){
//处理data
});
B组件:
globleEvents.on('handle', function(data){
//处理data
});