React 组件通讯

177 阅读2分钟
1、父传子

props

  • 可传递所有数据类型的数据
// 父组件
import React from "react";
import Footer from "@/components/footer";

export default function Home() {
  return (
    <div className="home-page">
    {/*父传子: 子组件身上绑定属性 属性名称可以自定义 保持语义化 */}
      <Footer active={"home"} />
    </div>
  );
}

// 子组件
import React from "react";

export default function Footer({active}) {
  return (
    <div className="footer-page">
      {active}
    </div>
  );
}
2、子传父
  • 子组件调用父组件传递过来的函数,并把想要传递的数据当成函数的实参
// 子组件
import React from "react";

function function Son({sonEvent}) {
  // 3.子组件函数触发父组件的函数实现子传父效果
  const onBtnClick = (val) => {
    sonEvent(val);
  };
  return (
    // 4.子组件函数触发父组件的函数实现子传父效果
    <div>我是函数组件<button onClick={()=>onBtnClick("实参")}>点击</button></div>
  )
}

export default Son;

// 父组件
import React from "react";

function function Father() {
  // 1.父组件准备一个函数
  const sonEvent = (val)=>{
    console.log(val);
  }

  return(
    <>
      {/* 2.父传子把函数给到子组件 */}
      <Son sonEvent={sonEvent}></Son>
    </>
  )

}

export default Father;
3、跨组件通讯
  • 利用 props 层层传递
  • 利用 context
// 1、通过React.createContext()创建一个context实例
import React from "react";

const DemoContext = React.createContext()

export default DemoContext;
// 2、通过provider创建一个生产者,provider有一个value属性可以用来包装所需要传递的数据
import React,{useState} from "react";
import Child from "./Child";
import DemoContext from './DemoContext'

export default function Demo(props) {
   const [value,setValue ]= useState("");
   const getValue = (val)=>{
     setValue(val)
   }

  return (
      <div>
        <h1>父组件</h1>
        <p>value: {value}</p>
        <button onClick={()=>getValue("bruce")}>点击</button>
        <DemoContext.Provider value={{
            value: value,
        }}>
          <Child></Child>
        </DemoContext.Provider>
      </div>
    )
}
// 3、通过Consumer创建一个消费者,用来接收传递的数据
import React from "react";
import DemoContext from "./DemoContext";
export default function GrandSon(props) {
    return (
        <div>
            <h1>孙子组件</h1>
            <DemoContext.Consumer>
            {/* Consumer中需要使用函数 */}
              {(value) => {
                return (
                    <div>
                      <p>value: {value.value}</p>
                    </div>
                )}
              }
            </DemoContext.Consumer>
        </div>
    )
}
// 中间组件
import React from "react";
import GrandSon from "./GrandSon";

export default function Child() {
    return (
        <div>
            <h1>子组件</h1>
            <GrandSon></GrandSon>
        </div>
    )
}
4、兄弟组件传值
  • 变量提升,兄弟组件通讯
expoer default function Son1(props) {
  return (
    <div>
      <p>Son1</p>
      <button onClick={() => { props.setText('我是Son1发的信息') }}>给Son2发信息</button>
    </div>
  )
}
export default function Son2(props) {
  return (
    <div>
      <p>Son2</p>
      <p>{props.text}</p>
    </div>
  )
}

function Father() {
  let [text, setText] = useState('')
  return (
    <>
      <div>Father</div>
      <Son1 setText={setText}></Son1>
      <Son2 text={text}></Son2>
    </>
  )
}
export default Father;
5、node 的 events 模块的单例通信
yarn add events
// eventBus.js 创建全局事件监管器
import { EventEmitter } from 'eventemitter3';

const eventBus = new EventEmitter();

export default eventBus;


// ComponentA.jsx
import React from 'react';
import eventBus from './eventBus';

export default function ComponentA {
  const emitEvent = () => {
    eventBus.emit('custom-event''这是传递的数据');
  };
  return (
    <div>
      <button onClick={() => emitEvent}>触发事件</button>
    </div>
  );
}

// ComponentB.jsx
import React, { useState, useEffect } from 'react';
import eventBus from './eventBus';

export default function ComponentB() {
  const [eventData, setEventData] = useState('');
  useEffect(() => {
    const eventBusListener = (data) => {
      setEventData(data);
      console.log('收到事件,数据为:', data);
    };
    eventBus.on('custom-event', eventBusListener);
    return () => {
      // 在组件卸载时取消事件监听
      eventBus.off('custom-event', eventBusListener);
    };
  }, []);
  return (
    <div>
      <p>{eventData}</p>
    </div>
  );
};