事件的监听(订阅)和事件的触发(发布)
事件和监听函数的对应关系“映射”,处理“映射”我们大部分情况下都是用对象来做的。所以说在全局我们需要设置一个对象,来存储事件和监听函数之间的关系:
constructor() {
// eventMap 用来存储事件和监听函数之间的关系
this.eventMap = {};
}
2.订阅
把事件和对应的监听函数写入到 eventMap 里面去:
// type 这里就代表事件的名称
on(type, handler) {
// hanlder 必须是一个函数,如果不是直接报错
if(!(handler instanceof Function)) {
throw new Error("需要传一个函数")
}
// 判断 type 事件对应的队列是否存在
if(!this.eventMap[type]) {
// 若不存在,新建该队列
this.eventMap[type] = []
}
// 若存在,直接往队列里推入 handler
this.eventMap[type].push(handler)
}
3.发布
发布操作就是一个“读”操作。
// 别忘了我们前面说过触发时是可以携带数据的,params 就是数据的载体
emit(type, params) {
// 假设该事件是有订阅的(对应的事件队列存在)
if(this.eventMap[type]) {
// 将事件队列里的 handler 依次执行出队
this.eventMap[type].forEach((handler, index)=> {
// 注意别忘了读取 params
handler(params)
})
}
}
4.关闭
关闭就是一个出队列的操作。
off(type, handler) {
if(this.eventMap[type]) {
this.eventMap[type].splice(this.eventMap[type].indexOf(handler)>>>0,1)
}
}
5.测试
完整代码
class myEventEmitter {
constructor() {
this.eventMap = {};
}
on(type, handler) {
if (!handler instanceof Function) {
throw new Error("请传一个函数");
}
if (!this.eventMap[type]) {
this.eventMap[type] = []
}
this.eventMap[type].push(handler)
}
emit(type, params) {
if (this.eventMap[type]) {
this.eventMap[type].forEach((handler) => {
handler(params);
})
}
}
off(type, handler) {
if (this.eventMap[type]) {
// 位运算 负数返回无限大的数,否则返回本身
this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1);
}
}
}
const myEvent = new myEventEmitter();
// 编写一个简单的 handler
const testHandler = function (params) {
console.log(`test事件被触发了,testHandler 接收到的入参是${params}`);
};
// 监听 test 事件
myEvent.on("test", testHandler);
// 在触发 test 事件的同时,传入希望 testHandler 感知的参数
myEvent.emit("test", "123");
// myEvent.off("test", testHandler);
console.log(`object`, myEvent.eventMap)
6.在React中应用
// index.jsx
import React, { Component } from 'react'
import A from './A'
import B from './B'
import event from './event.js'
class index extends Component {
render() {
React.$myEvent = new event()
return (
<div>
<A></A>
<B></B>
</div>
)
}
}
export default index
// event.js
class myEventEmitter {
constructor() {
this.eventMap = {};
}
on(type, handler) {
if (!handler instanceof Function) {
throw new Error("请传一个函数");
}
if (!this.eventMap[type]) {
this.eventMap[type] = []
}
this.eventMap[type].push(handler)
}
emit(type, params) {
if (this.eventMap[type]) {
this.eventMap[type].forEach((handler) => {
handler(params);
})
}
}
off(type, handler) {
if (this.eventMap[type]) {
this.eventMap[type].splice(this.eventMap[type].indexOf(handler) >>> 0, 1);
}
}
}
export default myEventEmitter
// A
import React from "react";
class A extends React.Component {
state = {
newParams: "",
};
handler = (params) => {
this.setState({
newParams: params,
});
};
bindHandler = () => {
React.$myEvent.on("someEvent", this.handler);
};
render() {
return (
<div>
<button onClick={this.bindHandler}>点我监听A的动作</button>
<div>A传入的内容是[{this.state.newParams}]</div>
</div>
);
}
}
export default A;
// B
import React from "react";
class B extends React.Component {
state = {
infoToB: "哈哈哈哈我来自A",
};
reportToB = () => {
React.$myEvent.emit("someEvent", this.state.infoToB);
};
render() {
return <button onClick={this.reportToB}>点我把state传递给B</button>;
}
}
export default B;