在React的江湖中,组件就像是各大门派的武林人士。有的位高权重如"父组件",有的初出茅庐如"子组件"。在这个世界里,内功心法(数据)的传递有着森严的等级和规矩。
很多初学者在面对组件通信时,往往会被各种 Props、Callback、Context 搞得晕头转向。其实,只要搞懂了数据的流向,这套武功秘籍也就融会贯通了。
今天,我们就用一套"武林法则",彻底拆解React中的四种核心通信方式。
一、父传子:盟主传授"单向秘籍"
这是最基础的招式。想象一下,父组件是武林盟主,手里有一本绝世武功《九阴真经》(State),他想把这套武功传给刚入门的小徒弟(子组件)。
江湖规矩:
- 授受不亲:盟主必须亲手把秘籍递给徒弟(在子组件标签上绑定属性)。
- 只读铁律:徒弟拿到秘籍后,只能研读修炼,绝对不能擅自涂改秘籍上的文字!如果徒弟试图修改 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),想要上报给盟主(父组件)。但江湖规矩森严,徒弟不能直接把招式塞进盟主的脑子里。
江湖规矩:
- 锦囊妙计:盟主需要先给徒弟一个"空锦囊"(函数)。
- 装入招式:徒弟在适当时机,把自己的新招式装进锦囊(调用函数并传参)。
- 飞鸽回传:锦囊一旦封好,就会自动飞回盟主手中,盟主打开锦囊,更新自己的内力(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)。大师兄想把自己的内力传给二师弟,怎么办?他们之间没有直接的经脉相连(无直接通信渠道)。
江湖规矩:
- 中转站:必须由师父(父组件)出面。
- 状态提升:大师兄先把内力传给师父(子传父),师父收到后,再把内力传给二师弟(父传子)。
这在武学中被称为"移花接木",在 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)。
江湖规矩:
- 建立广播台:使用 createContext 创建一个信号塔。
- 发功(Provider) :盟主在高处使用 Provider 发出信号,笼罩在信号范围内的所有后代。
- 接收(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 不侵!