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时候造成难以追踪定位问题点;

相关推荐
提子拌饭1336 分钟前
个人月事记录表应用 - 鸿蒙PC Electron框架完整实现指南
前端·javascript·华为·electron·前端框架·开源·鸿蒙系统
超人气王13 分钟前
新手学前端JS浅拷贝和深拷贝:对象复制竟然是个“替身文学”?
javascript·面试
YHL14 分钟前
📚 JS执行机制(执行上下文 + 调用栈 + 编译流程)
前端·javascript
不简说20 分钟前
这次真香!sv-print 可视化打印设计器更新:插件脚手架、Excel 导出、弹窗 API 三连发
前端·javascript·前端框架
无聊的老谢24 分钟前
Web GIS 最佳实践:Vue 集成 Leaflet/OpenLayers 实现基站海量点位渲染
前端·javascript·vue.js
yingyima28 分钟前
GCP Cloud Scheduler 核心语法与实战示例速查手册
前端
用户573501072520628 分钟前
Elpis 项目阶段性总结 - 基于 vue3 完成领域模型架构建设
前端
东风破_33 分钟前
V8 如何执行你的代码——编译、上下文与调用栈
javascript
假如让我当三天老蒯35 分钟前
为什么 setData 能获取到 prev 参数?(自学用)
前端·react.js
AskHarries1 小时前
Workspace:文件系统、项目上下文和执行边界
java·服务器·前端