React项目中使用发布订阅模式

React项目中使用发布订阅模式

发布订阅模式(也称观察者模式)是一种管理跨组件通信的有效方式,尤其是在不希望直接依赖于特定组件的情况下。这种模式允许一个对象(发布者)通知多个其他对象(订阅者),而不必知道这些对象是谁或他们在哪里。这有助于解耦组件,使得代码更加模块化和可维护。

1.创建发布订阅器

创建一个发布订阅器类,负责管理时间的注册、取消和触发

javascript 复制代码
# 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()
typescript 复制代码
# 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组件中使用这个发布订阅器。例如,一个组件可以订阅事件以接收数据,而另一个组件可以发布事件来发送数据。假设你有一个按钮组件,当点击时,他会触发一个事件发送一些数据

javascript 复制代码
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. 订阅数据

另一个组件可以订阅这个事件,并在接收到数据时执行某些操作

javascript 复制代码
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;
相关推荐
计算机安禾2 小时前
【c++面向对象编程】第22篇:输入输出运算符重载:<< 与 >> 的友元实现
java·前端·c++
redreamSo2 小时前
14 小时烧光 200 美金:Codex 和 Claude 的 /goal 命令打开了"放手跑"模式
前端
TingTing2 小时前
Webpack5 前端工程化建设
前端
A不落雨滴AI2 小时前
DKERP客户端重构纪实:4天自研控件库的“短命”教训,以及为什么我坚定选择原生Qt
前端
我叫黑大帅2 小时前
通过白名单解决 pnpm i 报错 Ignored build scripts
前端·javascript·面试
风止何安啊2 小时前
用 APP 背单词太无聊?我用 Trae Solo 移动端写个小游戏来准备 6级
前端·人工智能·trae
Summer不秃2 小时前
深入理解 Token 无感刷新:从并发雪崩到单例锁 + 请求队列的完整实现
前端·http
yingyima3 小时前
Git 实战:你必须掌握的 7 个常用命令
前端
次次皮3 小时前
代理启动前端dist包
java·前端·vue
Aphasia3114 小时前
React useState 的懒初始化机制
react.js