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

相关推荐
子兮曰14 小时前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰14 小时前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万14 小时前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝15 小时前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋15 小时前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁16 小时前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
李少兄16 小时前
JavaScript 隐式全局变量解析
javascript
汉堡大王952717 小时前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大18 小时前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师18 小时前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端