发布订阅模式
参考资料
- https://www.jianshu.com/p/c1be274d94cb
写在前面
订阅发布模式可以用在前端不同组件通讯的问题
正篇
简单来说就是通过在不同组件中引入一个公共类,该类中封装了一个存放key值,和方法队列的数组,以及一个订阅、触发、取消订阅的方法。使用时通过调用订阅方法并传入一个能够修改需要传递值的方法,订阅方法会将方法存放到对应key值的方法队列中。在需要传递值时通过调用触发方法,触发方法会依次调用对应key值的方法队列中的方法,从而对值进行修改。取消订阅的方法则是将对应的方法从方法队列中移除,下面是使用react hook的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| export default { listenList: {}, listen: function (key, fun) { if (!this.listenList[key]) { this.listenList[key] = []; } this.listenList[key].push(fun); }, tigger: function (key, value) { let funs = this.listenList[key]; if (!funs || funs.length === 0) { return false; } else { funs.forEach((fun) => { fun.apply(this, [value]); }); } }, remove: function(key, fun){ let funs = this.listenList[key]; if(!funs){ return false; } if(!fun){ fns && (fns.length = 0); }else{ for(let i = fns.length - 1; i >=0; i--) { if(fns[i] === fun) { fns.splice(i, 1) } } } }, };
|
组件一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import React, { useState, useEffect } from 'react'; import SubPub from '@/utils/SubPub.js';
export default function App() { const [price1, setPrice1] = useState(-1); const [price2, setPrice2] = useState(-1);
useEffect(() => { let changePrice1 = (value) => { console.log('comp1:', value); setPrice1(value); } SubPub.listen('price1', changePrice1);
let changePrice2 = (value) => { console.log('comp1:', value); setPrice2(value); } SubPub.listen('price2', changePrice2);
return ()=>{ SubPub.remove('price1', changePrice1); SubPub.remove('price2', changePrice2); } }, []); return ( <> <h2>This is comp1</h2> <h2>{price1}</h2> <h2>{price2}</h2> <button onClick={() => SubPub.tigger('price1', 1)}>prices1 to 1</button> </> ); }
|
组件二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import React, { useState, useEffect } from 'react'; import SubPub from '@/utils/SubPub.js';
export default function App() { const [price1, setPrice1] = useState(-1); const [price2, setPrice2] = useState(-1);
useEffect(() => { let changePrice1 = (value) => { console.log('comp2:', value); setPrice1(value); } SubPub.listen('price1', changePrice1);
let changePrice2 = (value) => { console.log('comp2:', value); setPrice2(value); } SubPub.listen('price2', changePrice2);
return ()=>{ SubPub.remove('price1', changePrice1); SubPub.remove('price2', changePrice2); } }, []); return ( <> <h2>This is comp2</h2> <h2>{price1}</h2> <h2>{price2}</h2> <button onClick={() => SubPub.tigger('price1', 2)}>prices1 to 2</button> </> ); }
|
应用这两个组件的类
1 2 3 4 5 6 7 8 9 10 11 12
| import React, { useState, useEffect } from 'react'; import P1 from '@/pages/page1/index.js'; import P2 from '@/pages/page2/index.js';
export default function App() { return ( <> <P1></P1> <P2></P2> </> ); }
|
最终效果