组件组合与 children
组件组合与 children · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
这一课解决「容器和内容怎么复用」:children prop 让组件把「内容」当参数收进来。读完你能实现 Card、Section 这类容器组件,并判断什么时候该用组合、而不是继续给组件加开关属性。
问题场景
页面上要三种卡片:普通卡片、带头部的卡片、带底部按钮的卡片。第一版做法是给 Card 不断加开关:
function Card({ showHeader, headerText, showFooter, footerText, children }) {
return (
<div className="card">
{showHeader && <header>{headerText}</header>}
{children}
{showFooter && <footer>{footerText}</footer>}
</div>
);
}
四个开关还不够——产品接着要「头部带关闭按钮」「底部放两个按钮」。每来一种新需求就加一个 prop,组件内部的条件分支越堆越多,最后没人敢动它。
核心解释
children 是组件标签之间的内容,本质上是一个 prop。 写 <Card><h3>标题</h3></Card> 时,中间那段 JSX 会作为 children 传进组件,想放哪就渲染到哪:
function Card({ children }) {
return <div className="card">{children}</div>;
}
组合的思路是「结构写在使用方,能力写在容器里」。卡片要头部?在使用方直接写:<Card><CardHeader title="..."/><p>正文</p></Card>。容器只负责统一的边框、间距、布局——它不知道也不关心里面是什么。这与函数设计的道理相同:让调用方传内容,比让组件枚举所有内容形态更可扩展。
多槽位布局也一样,children 只是一个特殊的 prop,其他 prop 同样可以传 JSX:
function Layout({ sidebar, content }) {
return (
<div className="row">
<aside>{sidebar}</aside>
<main>{content}</main>
</div>
);
}
什么时候用组合而不是加 prop?给个判断标准:新需求改变的是「内容或结构」时,用组合;改变的是「外观或行为的一个具体维度」时,加一个 prop 没问题。一旦发现自己在写 showHeader、showFooter、headerVariant="with-close" 这类开关,就该停下来换组合了。
示例拆解
实验区提供一个「开关地狱」对照组和一个组合实现,关键点如下:
CardWithFlags:靠showHeader、showFooter、footerText控制,演示区有一个「加需求」按钮,每点一次开关数量 +1,直观感受 prop 爆炸;Card:只收children,头部、正文、底部全由使用方拼装,容器代码永远三行;- 使用方
<Card><h4>...</h4><p>...</p><button>...</button></Card>展示了内容的自由度——放什么、放几个都行; Layout演示多槽位:sidebar与content两个 JSX prop 各归其位。
验证方式:两种实现的渲染结果可以做到一模一样,但 CardWithFlags 每加一种形态要改组件本身,组合版只改使用方——改动隔离在外,容器保持稳定。
动手任务
打开本课实验区,完成三个小改动:
- 用
Card组合出一张「带头部标题和底部按钮」的卡片,全程不改Card本身。 - 给
Layout的侧边栏和主区各换一种内容,体会槽位的灵活性。 - 把
CardWithFlags里的开关再减一半,看看剩下的分支还剩多少可读性。
常见错误
- 忘记渲染 children:容器收了 children 却没在 JSX 里输出
{children},使用方写了内容但页面空白。 - 把所有东西都做成 prop:
text、html、headerNode、footerNode传一堆 JSX prop,不如直接用 children 清晰。 - children 当普通变量用:它是 JSX(React 元素),不能直接
.map或改属性;要循环渲染请让使用方传数组。 - 容器插手内容逻辑:容器里写
if (children 某文本)做特殊处理,等于把开关逻辑换了个地方藏;容器只管布局和样式。
检查与复盘
完成下方检查题确认理解。自查清单:
- 能说出 children 的本质:一个内容为 JSX 的 prop
- 设计组件前先问「新需求动的是内容还是外观」,再决定用组合还是加 prop
- 审查组件时,看到成堆的 show 开关就能识别出「该组合了」
参考资料
- React 官方文档:通过 children 传递内容 —— children 的官方讲解
- React 官方文档:Thinking in React —— 从静态结构到组件层级划分的官方方法论
读完这一课了?
标记完成后,工作台会安排接下来的学习。