React父子组件通信:从“武林秘籍”看懂数据流向

在React的江湖中,组件就像是各大门派的武林人士。有的位高权重如"父组件",有的初出茅庐如"子组件"。在这个世界里,内功心法(数据)的传递有着森严的等级和规矩。

很多初学者在面对组件通信时,往往会被各种 Props、Callback、Context 搞得晕头转向。其实,只要搞懂了数据的流向,这套武功秘籍也就融会贯通了。

今天,我们就用一套"武林法则",彻底拆解React中的四种核心通信方式。

一、父传子:盟主传授"单向秘籍"

这是最基础的招式。想象一下,父组件是武林盟主,手里有一本绝世武功《九阴真经》(State),他想把这套武功传给刚入门的小徒弟(子组件)。

江湖规矩:

  1. 授受不亲:盟主必须亲手把秘籍递给徒弟(在子组件标签上绑定属性)。
  2. 只读铁律:徒弟拿到秘籍后,只能研读修炼,绝对不能擅自涂改秘籍上的文字!如果徒弟试图修改 Props,就会走火入魔(报错)。

代码演练:

父组件(盟主)将 name 传给子组件:

JavaScript

javascript 复制代码
// 父组件 Parent.jsx
import Child from "./Child";

export default function Parent() {
    const state = {
        name: '九阴真经' // 盟主手里的秘籍
    };
    return (
        <div>
            <h2>武林盟主(父组件)</h2>
            {/* 盟主发功:将秘籍打包成 msg 属性传给徒弟 */}
            <Child msg={state.name} />
        </div>
    );
}

子组件(徒弟)接收秘籍,谨记只读:

JavaScript

javascript 复制代码
// 子组件 Child.jsx
export default function Child(props) {
    // props.msg = '葵花宝典'; // 错误示范:徒弟不能擅自篡改秘籍,否则报错!
    
    return (
        <div>
            {/* 徒弟展示学到的招式 */}
            <h3>入室弟子(子组件)-- 习得:{props.msg}</h3>
        </div>
    );
}

核心心法:Props 是只读(Read-Only)的。数据流向是从上至下的单向流动,这保证了数据源的纯净和可追溯。

二、子传父:徒弟呈递"飞鸽传书"

有时候,青出于蓝而胜于蓝。徒弟(子组件)自己悟出了一套新招式(State),想要上报给盟主(父组件)。但江湖规矩森严,徒弟不能直接把招式塞进盟主的脑子里。

江湖规矩:

  1. 锦囊妙计:盟主需要先给徒弟一个"空锦囊"(函数)。
  2. 装入招式:徒弟在适当时机,把自己的新招式装进锦囊(调用函数并传参)。
  3. 飞鸽回传:锦囊一旦封好,就会自动飞回盟主手中,盟主打开锦囊,更新自己的内力(setState)。

代码演练:

父组件准备"锦囊"(函数):

JavaScript

javascript 复制代码
// 父组件 Parent.jsx
import { useState } from "react";
import Child from "./Child";

export default function Parent() {
    const [count, setCount] = useState(0);

    // 定义锦囊:这是一个用来接收徒弟数据的函数
    const receiveMove = (n) => {
        setCount(n); // 盟主收到招式后,更新自己的内力
    }

    return (
        <div>
            <h2>盟主内力值:{count}</h2>
            {/* 把锦囊(函数)传给徒弟 */}
            <Child getNum={receiveMove} />
        </div>
    );
}

子组件使用"锦囊"回传数据:

JavaScript

javascript 复制代码
// 子组件 Child.jsx
export default function Child(props) {
    const state = {
        num: 100 // 徒弟自创的新招式
    };

    function send() {
        // 关键一步:调用父组件给的函数,把数据作为参数传回去
        props.getNum(state.num);
    }

    return (
        <div>
            <h3>入室弟子</h3>
            <button onClick={send}>飞鸽传书给盟主</button>
        </div>
    )
}

核心心法 :React 中没有直接的"子传父"语法,本质是父组件将函数作为 Props 传递给子组件,子组件执行该函数

三、兄弟组件:盟主充当"中间人"

现在有两个徒弟:大师兄(Child1)和二师弟(Child2)。大师兄想把自己的内力传给二师弟,怎么办?他们之间没有直接的经脉相连(无直接通信渠道)。

江湖规矩:

  1. 中转站:必须由师父(父组件)出面。
  2. 状态提升:大师兄先把内力传给师父(子传父),师父收到后,再把内力传给二师弟(父传子)。

这在武学中被称为"移花接木",在 React 中叫状态提升(Lifting State Up)

代码演练:

父组件作为枢纽:

JavaScript

javascript 复制代码
// 父组件 Parent.jsx
import { useState } from "react";
import Child1 from "./Child1";
import Child2 from "./Child2";

export default function Parent() {
    const [message, setMessage] = useState("等待传功...");

    // 接收大师兄数据的锦囊
    const getFromChild1 = (msg) => {
        setMessage(msg);
    }

    return (
        <div>
            <h2>武林盟主(中转站)</h2>
            {/* 接收端:把函数给大师兄 */}
            <Child1 transfer={getFromChild1} />
            {/* 发送端:把收到的数据给二师弟 */}
            <Child2 msg={message} />
        </div>
    )
}

大师兄(发送方):

JavaScript

javascript 复制代码
// Child1.jsx
export default function Child1(props) {
    const energy = "混元霹雳手"; 
    return (
        <div>
            <button onClick={() => props.transfer(energy)}>
                大师兄:发送内力
            </button>
        </div>
    )
}

二师弟(接收方):

JavaScript

javascript 复制代码
// Child2.jsx
export default function Child2(props) {
    return (
        <div>
            {/* 展示从师父那里转交过来的大师兄的内力 */}
            <h3>二师弟:接收到的招式 -- {props.msg}</h3>
        </div>
    )
}

核心心法:兄弟不分家,全靠父当家。遇到兄弟通信,先找共同的父组件,把状态提升上去。

四、跨组件通信:狮子吼"全域广播"

如果门派等级森严,盟主要把消息传给徒弟的徒弟的徒弟(孙组件、重孙组件),一层层传 Props 实在是太慢了,而且容易出错(Prop Drilling)。

这时候,盟主会使用绝学"千里传音"或"狮子吼"(Context API)。

江湖规矩:

  1. 建立广播台:使用 createContext 创建一个信号塔。
  2. 发功(Provider) :盟主在高处使用 Provider 发出信号,笼罩在信号范围内的所有后代。
  3. 接收(Consumer/useContext) :任何层级的徒子徒孙,只要有 useContext 这个接收器,就能直接听到盟主的声音,无需中间人转述。

代码演练:

建立广播台(Context):

JavaScript

javascript 复制代码
// Context.js
import { createContext } from 'react';
export const SectContext = createContext(); // 创建门派广播台

父组件发功:

JavaScript

javascript 复制代码
// Parent.jsx
import { SectContext } from './Context';
import Child from "./Child";

export default function Parent() {
    return (
        <SectContext.Provider value={'武林至尊,宝刀屠龙'}>
            <div>
                <h2>盟主发出狮子吼</h2>
                <Child /> {/* 子组件内部包裹着孙组件 */}
            </div>
        </SectContext.Provider>
    );
}

孙组件(无需经过子组件)直接接收:

JavaScript

javascript 复制代码
// Grandson.jsx
import { useContext } from 'react';
import { SectContext } from './Context';

export default function Grandson() {
    // 越级接收:直接获取上下文中的数据
    const secret = useContext(SectContext);
    
    return (
        <div>
            <h4>徒孙接收到的广播:{secret}</h4>
        </div>
    );
}

核心心法:Context 能够打破组件层级的限制,实现数据的"隔空传送",非常适合处理主题颜色、用户登录状态等全局数据。

五、结语:武功谱总结

React 的组件通信,归根结底就是数据流向的管理。不要死记硬背代码,要理解数据是从哪里来,要到哪里去。

最后,附上一份"武功谱"供各位少侠修炼参考:

通信方式 适用场景 核心流向 隐喻
Props 父子通信 父 -> 子 盟主传秘籍(只读)
Callback 子父通信 子 -> 父 徒弟用锦囊飞鸽传书
状态提升 兄弟通信 子A -> 父 -> 子B 盟主做中间人移花接木
Context 跨级通信 Provider -> Consumer 狮子吼全域广播

愿各位在 React 的江湖中,内功深厚,Bug 不侵!

相关推荐
mCell7 小时前
如何零成本搭建个人站点
前端·程序员·github
mCell8 小时前
为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞
前端·设计模式·agent
恋猫de小郭9 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
少云清9 小时前
【安全测试】2_客户端脚本安全测试 _XSS和CSRF
前端·xss·csrf
萧曵 丶9 小时前
Vue 中父子组件之间最常用的业务交互场景
javascript·vue.js·交互
银烛木9 小时前
黑马程序员前端h5+css3
前端·css·css3
m0_607076609 小时前
CSS3 转换,快手前端面试经验,隔壁都馋哭了
前端·面试·css3
听海边涛声9 小时前
CSS3 图片模糊处理
前端·css·css3
IT、木易9 小时前
css3 backdrop-filter 在移动端 Safari 上导致渲染性能急剧下降的优化方案有哪些?
前端·css3·safari
0思必得09 小时前
[Web自动化] Selenium无头模式
前端·爬虫·selenium·自动化·web自动化