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;
相关推荐
liyang_ii5 小时前
createAsyncThunk
react.js
竟未曾年少轻狂5 小时前
Vue3 生命周期钩子
前端·javascript·vue.js·前端框架·生命周期
TT哇5 小时前
【实习】数字营销系统 银行经理端(interact_bank)前端 Vue 移动端页面的 UI 重构与优化
java·前端·vue.js·ui
蓝帆傲亦5 小时前
Web前端跨浏览器兼容性完全指南:构建无缝用户体验的最佳实践
前端
晴殇i5 小时前
【前端缓存】localStorage 是同步还是异步的?为什么?
前端·面试
不一样的少年_5 小时前
Chrome 插件实战:如何实现“杀不死”的可靠数据上报?
前端·javascript·监控
深度涌现5 小时前
DNS详解——域名是如何解析的
前端
小码哥_常5 小时前
Android内存泄漏:成因剖析与高效排查实战指南
前端
卤代烃5 小时前
✨ 形势比人强,Chrome 大佬也去搞 Gemini 了
前端·agent·vibecoding
偶像佳沛5 小时前
JS 对象
前端·javascript