提前聲明: 我沒(méi)有對(duì)傳入的參數(shù)進(jìn)行及時(shí)判斷而規(guī)避錯(cuò)誤,僅僅對(duì)核心方法進(jìn)行了實(shí)現(xiàn);
解決了react的非父子間的通信;
參考文檔:https://github1s.com/browserify/events/blob/main/events.js
? ? ? ? ? ? ? ? ?https://www.npmjs.com/package/events
? ? ? ? ? ? ? ? ?https://github.com/browserify/events
? ? ? ? ? ? ? ? ?
1.其中的一種實(shí)現(xiàn)的方式? ?
?
首先先新建一個(gè)文件eventBus.tsx
class EventBus {
constructor() {
this.events = this.events || new Map(); // 儲(chǔ)存事件/回調(diào)鍵值對(duì)
this.maxListeners = this.maxListeners || 10; // 設(shè)立監(jiān)聽(tīng)上限
}
// 觸發(fā)名為type的事件
emit(type, ...args) {
let handler = null;
handler = this.events.get(type);
console.log('?? ~ file: eventBus.js:11 ~ EventBus ~ emit ~ handler:', handler, args);
if (handler === undefined) {
return false;
}
if (Array.isArray(handler)) {
// 如果是一個(gè)數(shù)組說(shuō)明有多個(gè)監(jiān)聽(tīng)者,需要依次此觸發(fā)里面的函數(shù)
// eslint-disable-next-line no-plusplus
for (let i = 0; i < handler.length; i++) {
if (args.length > 0) {
handler[i].apply(this, args);
} else {
handler[i].call(this);
}
}
} else {
// 單個(gè)函數(shù)的情況我們直接觸發(fā)即可
// eslint-disable-next-line no-lonely-if
if (args.length > 0) {
handler.apply(this, args);
} else {
handler.call(this);
}
}
return true;
}
// 監(jiān)聽(tīng)名為type的事件
on(type, fn) {
const handler = this.events.get(type);
if (!handler) {
this.events.set(type, fn);
} else if (handler && typeof handler === 'function') {
// 如果handler是函數(shù)說(shuō)明只有一個(gè)監(jiān)聽(tīng)者
this.events.set(type, [handler, fn]); // 多個(gè)監(jiān)聽(tīng)者我們需要用數(shù)組儲(chǔ)存
} else {
handler.push(fn); // 已經(jīng)有多個(gè)監(jiān)聽(tīng)者,那么直接往數(shù)組里push函數(shù)即可
}
}
// eslint-disable-next-line consistent-return
remove(type, fn) {
const handler = this.events.get(type); // 獲取對(duì)應(yīng)事件名稱(chēng)的函數(shù)清單
if (handler && typeof handler === 'function') {
// 如果是函數(shù),說(shuō)明只被監(jiān)聽(tīng)了一次
this.events.delete(type, fn);
} else {
if (handler === undefined) {
return false;
}
let position = null;
// 如果handler是數(shù)組,說(shuō)明被監(jiān)聽(tīng)多次要找到對(duì)應(yīng)的函數(shù)
// eslint-disable-next-line no-plusplus
for (let i = 0; i < handler.length; i++) {
if (handler[i] === fn) {
position = i;
} else {
position = -1;
}
}
// 如果找到匹配的函數(shù),從數(shù)組中清除
if (position !== -1) {
// 找到數(shù)組對(duì)應(yīng)的位置,直接清除此回調(diào)
handler.splice(position, 1);
// 如果清除后只有一個(gè)函數(shù),那么取消數(shù)組,以函數(shù)形式保存
if (handler.length === 1) {
this.events.set(type, handler[0]);
}
} else {
return this;
}
}
}
}
const eventBus = new EventBus();
export default eventBus;
// 簡(jiǎn)單實(shí)現(xiàn)的發(fā)布訂閱模式 也是對(duì)的
// class EventEmitter {
// constructor() {
// this.eventBus = this.eventBus || {};
// }
// emit(type, params) {
// this.eventBus.type.forEach(item => {
// item(params);
// });
// }
// on(type, fn) {
// if (this.eventBus.type) {
// this.eventBus.type.push(fn);
// } else {
// this.eventBus.type = [fn];
// }
// }
// remove(type, fn) {
// if (this.eventBus[type]) {
// delete this.eventBus.type
// }
// }
// }
// const eventBus = new EventEmitter();
// export default eventBus;
然后再組件A使用=>接收
import React, { useState, useEffect, useCallback } from 'react';
// import eventBus from '@/utils/events';
import eventBus from '@/utils/eventBus';
const TopBox = () => {
const [num, setNum] = useState(0);
const addNum = useCallback((message: any) => {
setNum(message);
}, []);
useEffect(() => {
eventBus.on('emit', addNum);
return () => {
if(eventBus) {
eventBus.remove('emit', addNum);
}
};
}, []);
return (
<div>
<span>我也不知道是什么111: {num}</span>
</div>
);
};
export default TopBox;
然后再組件B使用=>觸發(fā)
import React, { useState } from 'react';
import { Button } from 'antd';
// import eventBus from '@/utils/events';
import eventBus from '@/utils/eventBus';
const TopBox = () => {
const [num,setNum] = useState(0)
const addNum = () => {
const numNew = num + 1;
setNum(numNew);
eventBus.emit('emit', numNew)
}
return (
<div>
<Button onClick={() => {addNum()}}>按鈕</Button>
<span>我也不知道是什么:{num}</span>
</div>
);
};
export default TopBox;
?
?
2.其中的另一種實(shí)現(xiàn)的方式
安裝這個(gè)events插件
yarn add events
新建一個(gè)文件evnets.ts
import { EventEmitter } from 'events';
export default new EventEmitter();
組件A使用
import React, { useState, useEffect, useCallback } from 'react';
import eventBus from '@/utils/events';
// import eventBus from '@/utils/eventBus';
const TopBox = () => {
const [num, setNum] = useState(0);
const addNum = useCallback((message: any) => {
setNum(message);
}, []);
useEffect(() => {
eventBus.on('emit', addNum);
return () => {
if(eventBus) {
// eventBus.remove('emit', addNum);
eventBus.removeListener('emit', addNum);
}
};
}, []);
return (
<div>
<span>我也不知道是什么111: {num}</span>
</div>
);
};
export default TopBox;
組件B使用文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-417306.html
import React, { useState } from 'react';
import { Button } from 'antd';
import eventBus from '@/utils/events';
// import eventBus from '@/utils/eventBus';
const TopBox = () => {
const [num,setNum] = useState(0)
const addNum = () => {
const numNew = num + 1;
setNum(numNew);
eventBus.emit('emit', numNew)
}
return (
<div>
<Button onClick={() => {addNum()}}>按鈕</Button>
<span>我也不知道是什么:{num}</span>
</div>
);
};
export default TopBox;
?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-417306.html
到了這里,關(guān)于JavaScript 發(fā)布-訂閱設(shè)計(jì)模式實(shí)現(xiàn) React EventBus(相當(dāng)于vue的$Bus)非父子之間通信的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!