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.在组件中使用发布订阅器
在你的React组件中使用这个发布订阅器。例如,一个组件可以订阅事件以接收数据,而另一个组件可以发布事件来发送数据。假设你有一个按钮组件,当点击时,他会触发一个事件发送一些数据
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;