一个组件是否能同时发布和订阅?一个组件是否能同时订阅多个数据?(以函数式组件为例)

1.发布和订阅的一般操作流程

  1. 安装包 npm install pubsub-js
  2. 组件A想获取到组件B的消息C,发布订阅可以不用考虑组件AB的关系(父子、兄弟、祖孙等),
  3. 组件A,在刚挂载结束,就进行消息订阅,Pubsub.subscribe("C",(msg, data) => {console.log(msg,data)}
  4. 组件B,在获取到数据时,就进行消息发布,Pubsub.publish("C", {class:value,option:props.option});
  5. 当组件A检测到C发生变化,组件A中就拿到了数据,并进行数据处理,或发送请求或发送别的。这个监测就用到了useEffects

2.useEffect

  1. useEffect用来处理副作用,什么是副作用?什么是纯的?简单来说,纯的就是传入了a,b两个参数,那么这个纯的就不能修改外部数据或者依赖外部数据且只能作a与b的计算;副作用就是在很多情况下除了处理传入参数a、b,还可能修改局部变量、dom、console.log()等等。
  2. useEffect的处理时机可以看做 react类组件 中componentDidMount(刚挂载结束)componentDidUpdate(组件更新后) 和 componentWillUnmount(组件将要卸载) 这三个生命周期函数的组合。
  3. useEffect()有两个参数,第一个参数是要执行的函数,第二个参数是一个依赖项数组(根据需求第二个参数可选择性填写),根据数组里的变量是否变化决定是否执行函数。第二个参数不写,页面刷新一次,useEffect中的函数就会刷新一次;第二个参数为空数组[],useEffect中的函数只执行一次;如果有变量,该变量发生变化就执行一次。

 

useEffect(() => {
    // 订阅消息,另外两个产生数据的组件里发布数据
    var token = Pubsub.subscribe("conditionData", async (msg, data) => {
      setCD(data);
      console.log(msg, data);
      
      // 向后端发送请求获取数据,然后传递给父组件
      try {
        const response = await reqSearchStudent(
          {
            data: data,
          });
        console.log("请求成功", response);
        if (response.data.status === 0) {
          alert(response.data.msg)
        } else if (response.data.status === 1) {
          console.log(response.data.docs);
          response.data.docs.key = 1;
          setTabData(response.data.docs)
        }
      } catch (error) {
        console.log("请求失败", error);
      }
    })
    return () => Pubsub.unsubscribe(token)
  }, [conditionData])

 

3.一个组件是否可以既订阅又发布呢?

场景:组件A要订阅组件B时,B又要订阅组件A,A要用B的数打印,B要用A的数据打印

是可以的,在整个实验过程中,A组件和B组件都能获取到对方发布的数据,代码如下:

 

//组件A
import React, { useEffect, useState } from 'react' import PubSub from 'pubsub-js' export default function A() { const [b,setB] = useState(0); // useEffect用来检测b变动,变动就打印数据 useEffect(()=>{ // 订阅消息b let token = PubSub.subscribe('b',(msg,data)=>{ setB(data); console.log('a监测到b数据变化了') console.log(msg,data) }) return ()=>PubSub.unsubscribe(token) },[b]) const changeA = ()=>{ const a = document.getElementById('a'); let c = parseInt(a.value) + b; a.value = c; // 发布数据 PubSub.publish('a',c); } return ( <div> <input type="text" id='a'/> <button onClick={changeA}>点击</button> </div> ) }
//组件B
import React, { useEffect, useState } from 'react' import PubSub from 'pubsub-js' export default function B() { const [a,setA] = useState(1); // useEffect用来检测b变动,变动就打印数据 useEffect(()=>{ // 订阅消息b let token = PubSub.subscribe('a',(msg,data)=>{ console.log('b监测到a数据变化了') setA(data); console.log(msg,data) }) return ()=>PubSub.unsubscribe(token) },[a]) const changeB = ()=>{ const b = document.getElementById('b'); let c = parseInt(b.value) - a; b.value = c; // 发布数据 PubSub.publish('b',c); } return ( <div> <input type="text" id='b'/> <button onClick={changeB}>点击</button> </div> ) }

4.一个组件能否同时订阅多个组件的数据

场景:Test同时订阅组件A与组件B的数据   可以

import React from 'react'
import A from './A'
import B from './B'
import { useState,useEffect } from 'react'
import PubSub from 'pubsub-js'
export default function Test() {
  const [b,setB] = useState(0);
  const [a,setA] = useState(0);
    // useEffect用来检测b变动,变动就打印数据
    useEffect(()=>{
        // 订阅消息b
        let tokenA = PubSub.subscribe('a',(msg,data)=>{
            setA(data);
            console.log('T监测到a数据变化了')
            console.log(msg,data)
        })
     //这里如果不取消订阅,那么每次刷新页面,触发都会产生新的token,组件也会被多执行
return ()=>{PubSub.unsubscribe(tokenA)} },[a])
useEffect(()=>{
        // 订阅消息b
        let tokenB = PubSub.subscribe('b',(msg,data)=>{
            setB(data);
            console.log('T监测到b数据变化了')
            console.log(msg,data)
        })
     //这里如果不取消订阅,那么每次刷新页面,触发都会产生新的token,组件也会被多执行 return ()=>{PubSub.unsubscribe(tokenB);} },[b])
const changeT = ()=>{ const t = document.getElementById('t'); let c = parseInt(t.value) + b + a; t.value = c; // // 发布数据 // PubSub.publish('t',c);  } return ( <div> <A/> <hr /> <B/> <hr/> <input type="text" id='t' /> <button onClick={changeT}>点击</button> </div>  ) }

效果:

 

 

 

posted @ 2022-08-15 17:27  乔十六  阅读(98)  评论(0编辑  收藏  举报