React第十二节组件之间通讯之发布订阅模式(使用pubsub-js插件)

组件之间通讯常用方案
1、通过props
2、通过context
3、通过发布订阅模式
4、通过Redux 后面会有专栏介绍

1、安装 pubsub-js 插件 yarn add pubsub-js

常用的事件

a、发布事件 :传入一个自定义事件名称(name),以及要发布的消息内容(messagePubsub.publish('name', 'message')

还可以进行异步发布 Pubsub.publishSync('name', 'message')

b、订阅事件 :传入发布事件的的名称 (name),以及接收name事件传递参数的回调函数 callback,最终会返回一个类似setTimeout 的timer 用于标记当前订阅的事件,在取消订阅时候可以之间传入此值 let sub0 = Pubsub.subscribe('name', callback)

c、取消订阅
Pubsub.unsubscribe('name') // 可以传入发布事件名称进行取消
Pubsub.unsubscribe(sub0) // 还可以传入 订阅事件返回的标识进行取消

2、在发布事件组件中引入

相对于自定义的发布订阅器要简单一些

可以同时发布多个事件

javascript 复制代码
// 引入插件
import PubSub  from 'pubsub-js'
export default function ChildA() {
    const handlePublish = () => {
        // 调用发布事件
        PubSub.publish('onChangeName', '修改名称')
    }
  return (
    <div style={{background:'blue'}}>
      <h3>组件A</h3>
      <button onClick={handlePublish}>发布</button>
    </div>
  )
}

3、在订阅组件中使用

可以订阅多个事件,取消多个事件

javascript 复制代码
import { useEffect, useState } from "react"
import PubSub from "pubsub-js"
export default function ChildB() {
    const [name, setName] = useState('')
    const handleEvents = (fncName, data) => {
        /***
         * @description 回调函数接收两个参数
         * @param {String} fncName 发布的函数名称,例如:onChangeName
         * @param {any} data 发布传递的数据消息
         * */ 
        console.log('=msg==', fncName, data)
        // 通过 useState 的set 函数进行视图更新
        setName(data)
    }
    useEffect(() => {
        // 订阅事件
        let token1 = PubSub.subscribe('onChangeName',handleEvents)
        return () => {
            PubSub.unsubscribe('onChangeName')  // 卸载时解除订阅
            // 两种卸载时候取消订阅方案
            // PubSub.unsubscribe('token1')  // 卸载时解除订阅
        }
    }, [])

  return (
    <div>
      <h3>组件B</h3>
      <p>组件A传递消息: {name}</p>
    </div>
  )
}

4、在父组件中使用

javascript 复制代码
import ChildA from './childA'
import ChildB from './childB'
export default function MyPubsub() {
  return (
    <div style={{background: 'red', padding: '12px', width: '360px', height: '500px'}}>
        <h2>父组件</h2>
        <ChildA></ChildA>
        <hr />
        {/* 完全独立的两个子组件 */}
        <ChildB></ChildB>  
    </div>
  )
}

注意:

a、不管是自定义发布订阅器,还是直接使用插件,在组件卸载时候,都有将当前组件的订阅取消,避免过多订阅运行,导致内存溢出

b、使用插件,相对更加方便简洁,只需要关注及时调用 api既可以,不需要注意发布订阅器里面的逻辑

c、要避免多状态,多个发布订阅器存在多组件中,会在出现bug时候造成难以追踪定位问题点;

相关推荐
天平2 小时前
油猴脚本创建webworker踩坑记录
前端·javascript·typescript
原则猫4 小时前
前端基础大厦
前端
陈随易5 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart6 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒8 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰8 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
山河木马8 小时前
渲染管线-计算得到gl_Position(顶点着色器)之后续GPU流程
javascript·webgl·图形学
竹林8189 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花9 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu122710 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude