React项目中使用发布订阅模式
1.创建发布订阅器
# js
class PubSub {
constructor(){
this.events = {}
}
subscribe(event, callback){
if(!this.events[event]){
this.events[event] = []
}
this.events[event].push(callback)
}
unsubscribe(event,callback){
if(this.events[event]){
this.events[event] = this.events[event].filter(
cb => cb !== callback
)
}
}
publish(event,data){
if(this.events[event]){
this.events[event].forEach(callback => callback(data))
}
}
}
const pubsub = new PubSub()
# ts
interface EventMap {
[eventName: string]: any;
}
class EventCenter {
private listeners = {}
constructor(){
this.listeners = {}
}
subscribe<T extends keyof EventMap>(event: T, callback: (data?: EventMap[T]) => void) {
if(!this.listeners[event]) {
this.listeners[event] = []
}
this.listeners[event].push(callback)
}
publish<T extends keyof EventMap>(event: T, data?: EventMap[T]) {
const callbacks = this.listeners[event]
if(callbacks) {
callbacks.forEach(callback => {
callback(data)
})
}
}
unsubscribe<T extends keyof EventMap>(event: T, callback?: (data: EventMap[T]) => void) {
const callbacks = this.listeners[event];
if (callbacks) {
if (callback) {
this.listeners[event] = callbacks.filter(cb => cb !== callback);
} else {
delete this.listeners[event];
}
}
}
}
export default new EventCenter()
2.在组件中使用发布订阅器
import React from 'react';
import { pubsub } from './pubsub'; // 引入上面定义的PubSub实例
class ButtonComponent extends React.Component {
handleClick = () => {
pubsub.publish('dataUpdated', { message: 'Hello World!' });
};
render() {
return (
<button onClick={this.handleClick}>
Click me!
</button>
);
}
}
3. 订阅数据
import React, { useEffect, useState } from 'react';
import { pubsub } from './pubsub'; // 引入上面定义的PubSub实例
interface DisplayProps {}
interface DisplayState {
message: string;
}
const DisplayComponent: React.FC<DisplayProps> = () => {
const [message, setMessage] = useState('');
useEffect(() => {
const handleDataUpdate = ({ message }: { message: string }) => {
setMessage(message);
};
pubsub.subscribe('dataUpdated', handleDataUpdate);
return () => {
pubsub.unsubscribe('dataUpdated', handleDataUpdate);
};
}, []);
return <div>{message}</div>;
};
export default DisplayComponent;