事件的监听(订阅)和事件的触发(发布)
事件和监听函数的对应关系“映射”,处理“映射”我们大部分情况下都是用对象来做的。所以说在全局我们需要设置一个对象,来存储事件和监听函数之间的关系:
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] = []}// 若存在,直接往队列里推入 handlerthis.eventMap[type].push(handler)}
3.发布
发布操作就是一个“读”操作。
// 别忘了我们前面说过触发时是可以携带数据的,params 就是数据的载体emit(type, params) {// 假设该事件是有订阅的(对应的事件队列存在)if(this.eventMap[type]) {// 将事件队列里的 handler 依次执行出队this.eventMap[type].forEach((handler, index)=> {// 注意别忘了读取 paramshandler(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();// 编写一个简单的 handlerconst 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.jsximport 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.jsclass 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
// Aimport 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;
// Bimport 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;

