React 中的发布订阅模式

article/2025/10/27 0:25:00

1、react 通信

react的数据流是单向的, react 通信有以下几种方式:

单向数据流:指当前组件的 state 以 props 的形式流动时只能流向组件树中比自己层级更低的组件

  • 父向子通信:父组件提供state,并且内部设置好数据,子组件中通过 props 接收父组件中传递的数据
  • 子向父通信:父组件向子组件传一个函数,然后通过这个函数的回调,拿到子组件传过来的值
  • 父向孙通信:利用context传值。React.createContext()
  • 兄弟间通信:
    • 找一个相同的父组件,既可以用props传递数据,也可以用context的方式来传递数据。
    • 用一些全局机制去实现通信,比如redux等
    • 发布订阅模式

问题:利用props传递数据单层之间传递很方便,可是遇到多层传递就会比较麻烦,那么怎样解决多层传递的问题那? -----> 发布订阅模式

2、发布订阅模式

组件间通信需要引用一个类的实例,使用单例模式实现。

在 发布/订阅模式 有 发布者 和 订阅者,它们通过信道链接到一起。其主要包含三个对象:

订阅者:订阅一个或者多个信道消息的对象。

发布者:消息的发布者,往信道中投递消息的对象。

信道:每个信道都有一个名字,信道的实现细节对用户代码来说是隐藏的。

3、订阅 / 发布模型API设计思路

  • on(): 负责注册事件的监听(订阅),指定事件触发(发布)时的回调函数;
  • emit(): 负责触发事件,可以通过传参使其在触发的时候携带数据
  • off():负责监听器的删除(解除事件)

事件和监听函数的对应关系

constructor(){//eventMap 用来存储事件和监听函数之间的关系this.eventMap={}
}

实现订阅

//type 代表事件的名称
on(type,handler){//handler 必须是一个函数,如果不是直接报错if(!(handler instanceof Function)){throw new Error("请重新上传参数")
}
//判断type事件对应的队列是否存在
if(!(this.eventMap[type]){//若不存在,新建该队列this.eventMap[type]=[]//若存在,直接往队列里推入handlerthis.eventMap[type].push(handler)
})
}

实现发布

//触发时可以携带数据,params就是数据的载体
emit(type.params){
//假设该事件是有订阅的(对应的事件队列存在)
if(this.eventMap[type]){
//将事件队列里的handler依次执行出队
this.eventMap[type].forEach((handler,index)=>{
//注意别忘了读取params
handler(params)
})
}
}
//解除绑定
off(type,handler){
if(this.eventMap[type]){this.eventMap[type].splice(this.eventMap[type].indexOf(handler)>>>0,1)
}
}

完整代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>class myEventEmitter{constructor(){//eventMap 用来存储事件和监听函数关系this.eventMap={};}// 1.on注册事件监听器on(type,handler){//type 代表事件的名称,handler 必须是一个函数,如果不是直接报错if(!(handler instanceof Function)){throw new Error("请重新上传参数")}//判断type事件对应的队列是否存在if(!this.eventMap[type]){//若不存在,新建该队列this.eventMap[type]=[];console.log("注册成功");}else{//若存在,直接往队列里推入handlerthis.eventMap[type].push(handler)}}// 2.如何发布emit(type,params){    //params携带数据//假设该事件是有订阅,即存在对应的事件队列if(this.eventMap[type]){//将事件队列里的handler依次执行出队this.eventMap[type].forEach((handler,index)=>{//需要读取paramshandler(params)});console.log('发布成功');}}//解除绑定off(type,handler){if(this.eventMap[type]){this.eventMap[type].splice(this.eventMap[type].indexOf(handler)>>>0,1);  //>>>无符号向右移动符}console.log("解除成功");}}//测试代码//实例化myEventEmitterconst myEvent = new myEventEmitter();//写handlerconst testHandler = function(params){console.log(`test事件被触发了,testHandler接收到的入参是${params}`);};//监听test事件myEvent.on("test",testHandler);//触发test事件的同时,传入希望testHandler感知的参数myEvent.emit("test",testHandler("newState"));//解除myEvent.off("test",testHandler);</script>
</body>
</html>

结果展示
在这里插入图片描述

4、观察者模式
在这种模式中,一个目标对象(被观察者)管理所有的依赖于它的对象(观察者),并且在它本身的状态发生变化的时候主动发出通知。

其主要包含两个对象:

被观察者和观察者

缺点

耦合问题:每个观察者必须和被观察对象绑定在一起,这引入了耦合

性能问题:在最基本的实现中观察对象必须同步地通知观察者。这可能会导致性能瓶颈。


http://chatgpt.dhexx.cn/article/ZUDyDVE8.shtml

相关文章

深入Vue原理_全面剖析发布订阅模式

文章目录 发布订阅模式优化优化思路思考理解发布订阅模式(自定义事件)收集更新函数触发更新函数6.5 总结 总结写在最后本期推荐 欢迎各位小伙伴们&#xff01; 为大家推荐一款刷题神奇哦 点击链接访问牛客网 各大互联网大厂面试真题。从基础到入阶乃至原理刨析类面试题 应有尽有…

观察者模式VS发布订阅模式区别

观察者模式VS发布订阅模式区别 观察者模式&#xff1a;订阅者收集函数&#xff0c;发布者循环调用 发布订阅&#xff1a;收集发布单独给一个中介 对比 以结构来分辨模式&#xff0c;发布订阅模式相比观察者模式多了一个调度中心&#xff1b; 以意图来分辨模式&#xff0c;都…

RabbitMQ:发布订阅模式

✨ RabbitMQ:发布订阅模式 1.订阅模式基本介绍2.交换机3.发布订阅模式3.1基本介绍3.2生产者3.3消费者3.4测试 &#x1f4c3;个人主页:不断前进的皮卡丘 &#x1f31e;博客描述:梦想也许遥不可及&#xff0c;但重要的是追梦的过程&#xff0c;用博客记录自己的成长&#xff0c;记…

JavaScript设计模式:四、发布订阅模式

JavaScript设计模式&#xff1a;四、发布订阅模式 文章目录 JavaScript设计模式&#xff1a;四、发布订阅模式一、概述1. 观察者模式2. 发布订阅模式3. 观察者模式是不是发布订阅模式 一、概述 观察者模式&#xff1a; 观察者&#xff08;Observer&#xff09;直接订阅&#x…

发布订阅模式理解

发布订阅模式理解 1.发布-订阅模式 发布订阅模式是一种一对多的对象对应关系&#xff0c;多个观察者同时监听某一个对象&#xff0c;当该对象发生改变时&#xff0c;就会执行一个发布事件&#xff0c;这个发布事件会通知所有的事件订阅者&#xff0c;事件订阅者根据得到的数据…

JS观察者模式和发布订阅模式

观察者模式 观察者模式在前端工程中是很常见的设计模式&#xff0c;因为前端交互中充斥着大量多控件联动的交互&#xff0c;当参与联动的组件数量比较多或者组件数量可能变化的时候&#xff0c;代码就会变得难以维护。但是如果我们写代码时遵循了观察者模式的设计&#xff0c;…

redis发布订阅模式详解

文章目录 写在前面发布订阅的使用SUBSCRIBE命令PUBLISH命令注意发布、订阅客户端启动顺序&#xff01; PUBSUB命令PUNSUBSCRIBE命令UNSUBSCRIBE命令PSUBSCRIBE命令 总结 写在前面 Redis 发布订阅 (pub/sub) 是一种消息通信模式&#xff1a;发送者 (pub) 发送消息&#xff0c;订…

Vue发布订阅模式

简单的来说一下在别人问你这个问题的时候怎么来回答它 前端新人&#xff0c;如有错误求大佬指出~求教&#x1f49d; 情景复现 大佬提问&#xff1a;“你知道Vue发布订阅模式是什么吗&#xff1f;" 我的回答&#xff1a;“发布订阅模式其实是一种对象间一对多的依赖关系&…

观察者模式和发布订阅模式

一、概念 观察者(Observer)&#xff0c;又称发布-订阅&#xff08;Publish-Subscrice&#xff09;&#xff0c;属于23中设计模式之一。 发布订阅模式定义了一种一对多的依赖关系&#xff0c;让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身状态变化时&#xff0c…

C++发布订阅模式

C发布订阅模式 发布订阅模式主要包含三个部分&#xff1a;消息发布、消息订阅者、消息处理中心。与观察者模式相比多出了消息处理中心模块&#xff0c;这样在结构上可以解耦订阅者与发布者&#xff0c;功能上更加的丰富。 观察者模式 结构设计 有一个消息list&#xff0c;主…

Java实现发布订阅模式

什么是发布订阅模式 发布订阅模式是软件开发者很常见的一种设计模式&#xff0c;很多开源库都使用了发布订阅模式&#xff0c;例如RxJava、EventBus、Vue等&#xff0c;所以学习该模式还是很有必要的。 该模式中存在一个或多个发布者&#xff0c;一个或多个订阅者&#xff0c…

设计模式 —— 发布订阅模式

设计模式 —— 发布订阅模式 《工欲善其事&#xff0c;必先利其器》 我在之前有写过一篇关于 《观察者模式》 的文章&#xff0c;大家有兴趣的可以去看看&#xff0c;个人认为那个例子还是挺生动的。&#xff08;狗头&#xff09; 不过今天我们要学习的是&#xff0c;发布订阅…

小侃设计模式(十八)-发布订阅模式

1.概述 发布订阅模式又叫观察者模式&#xff08;Observer Pattern&#xff09;&#xff0c;它是指对象之间一对多的依赖关系&#xff0c;每当那个特定对象改变状态时&#xff0c;所有依赖于它的对象都会得到通知并被自动更新&#xff0c;它是行为型模式的一种。观察者模式内部…

发布-订阅模式

发布-订阅模式 学习知识要善于思考&#xff0c;思考&#xff0c;再思考。 —— 爱因斯在众多设计模式中&#xff0c;可能最常见、最有名的就是发布 - 订阅模式了&#xff0c;本篇我们一起来学习这个模式。 发布 - 订阅模式 &#xff08;Publish-Subscribe Pattern, pub-sub&a…

什么是发布订阅模式?

发布-订阅模式&#xff08;Publish-Subscribe pattern&#xff09;是一种软件架构模式&#xff0c;用于实现组件之间的解耦和消息传递。在这种模式中&#xff0c;组件&#xff08;发布者&#xff09;将消息发送到一个中心&#xff08;消息代理或主题&#xff09;&#xff0c;然…

发布订阅模式

零、目录 应用场景实现原理代码实现全局模式下的订阅发布模式&#xff08;泛化的订阅发布模式&#xff09;总结 一、应用场景 ​ 发布订阅模式&#xff0c;广泛的存在于在我们的生活之中。 ​ 举个一个简单的例子来说&#xff0c;当我们在浏览视频或者博客论坛之类的网…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:VLCPlayer

本文简述如何在Smobiler中使用VLCPlayer插件&#xff0c;该插件支持播放rtsp流。 Step 1. 新建一个SmobilerForm窗体&#xff0c;再拖入VLCPlay&#xff0c;布局如下 在设计器中给VLCPlayer.Url赋值或者在窗体的Load事件中赋值 演示使用的rtsp流地址 rtsp://wowzaec2demo.strea…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:TTS

本文简述如何在Smobiler中使用TTS文字转语音。 Step 1. 新建一个SmobilerForm窗体&#xff0c;并在窗体中加入TTS和Button&#xff0c;布局如下 Button的点击事件代码&#xff1a; private void button1_Press(object sender, EventArgs e){ //第一个参数为文本&#xff1b;第…

Smobiler 仿得到APP个人主页

原型如下&#xff1a; 完整代码参考 https://github.com/comsmobiler/BlogsCode/blob/master/Source/BlogsCode_SmobilerForm/MyForm/dedao.cs 思路 可以将原型按照上图分成2个部分&#xff0c;部分A可以使用label、image、button、imagebutton、fontIcon控件来实现&#xff…

.NET(C#、VB)APP开发——Smobiler平台控件介绍:PDFView

本文简述如何在Smobiler中使用PDFView。 Step 1. 新建一个SmobilerForm窗体&#xff0c;再拖入PDfView&#xff0c;布局如下 PDFView.ResourcrPath默认Document&#xff0c;指项目下\Resources\Document&#xff0c;若是pdf文件放在该文件夹下&#xff0c;则在设计器中直接赋值…