功能背景
想要实现类似于vue的eventBus的功能,由一个组件通知其他一个或多个组件。应用场景:比如一个可视化大屏的界面,当筛选条件变化的时候,要同时通知到大屏中所有图表一起变化。(当然使用store也是可以的,eventbus就是相当于多了一个解决方案)
代码实现
eventBus.js
// eventbus.js
const eventBus = {};
const events = {};
eventBus.on = (eventName, callback) => {
if (!events[eventName]) {
events[eventName] = [];
}
events[eventName].push(callback);
};
eventBus.emit = (eventName, data) => {
if (!events[eventName]) {
return;
}
events[eventName].forEach((callback) => {
callback(data);
});
};
export default eventBus;
子组件
import { Button } from 'antd';
import React from 'react';
import { useEffect, useState,useRef } from 'react'
import eventBus from '@/utils/eventBus';
const SonComponent = ({ dialogVisible, updateVisible }) => {
const _visible = {
get() {
return dialogVisible;
},
set(val) {
//广播子组件的状态改变
updateVisible && updateVisible(val);
},
};
const ctrlChoosen = (event) => {
_visible.set(event.target.checked);
};
const closeVisible = () => {
_visible.set(false);
};
//这里实现eventBus的监听,监听父组件的传参
useEffect(() => {
eventBus.on('buttonClick', (val) => {
//do some thing
console.log('子组件监听到',val)
});
return () => {
eventBus.off('buttonClick');
};
}, []);
return (
<div>
<Button onClick={closeVisible}>子组件控制关闭</Button>
<br></br>
<input type="checkbox" checked={_visible.get()} onChange={ctrlChoosen} />
<label>子组件状态{_visible.get()?'开':'关'}</label>
</div>
);
};
export default SonComponent;
父组件
import SonComponent from './Son'
import eventBus from '@/utils/eventBus';
<h1>父子组件eventBus交互</h1>
<SonComponent dialogVisible={dialogVisible} updateVisible={subscribeVisible} />
<Button onClick={()=>{eventBus.emit('buttonClick', true)}}>EVENTBUS父组件控制打开</Button>
实际效果
两个子组件均监听到了