功能背景
想要实现类似于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 thingconsole.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>
实际效果
两个子组件均监听到了