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;
相关推荐
有一个好名字24 分钟前
claude code安装
linux·运维·前端
BIBABULALA34 分钟前
Mini Virtual Machine — 可视化虚拟机模拟器(91行)
前端·css·css3
筱璦42 分钟前
期货软件开发「启动加载页 / 初始化窗口」
前端·c#·策略模式·期货
只与明月听1 小时前
RAG深入学习之Emabedding
前端·python·面试
We་ct1 小时前
React Scheduler & Lane 详解
前端·react.js·前端框架·reactjs·个人开发·任务调度·优先
kgduu1 小时前
js之json处理
前端·javascript·json
@木尘1 小时前
前端面试【 八股文篇】
前端·面试·职场和发展
吴佳浩1 小时前
OpenClaw、Claude Code 等 Agent 为什么都选择 Node.js?
前端·人工智能·langchain
小小小小宇2 小时前
React 19 useActionState 深度解析 & Vue 2.7 移植实战
前端
远山枫谷2 小时前
Vue2 vs Vue3 全面对比(含代码示例+迁移指南)
前端·vue.js