从
props到嵌套组件,带你玩转 React 的父子情深(不是)
🎯 开篇暴击:你写的代码,像不像一锅乱炖?
有没有过这样的经历:
- 父组件的数据想传给子组件?写个函数层层往下塞。
- 子组件想改父组件的状态?回调函数、状态提升、useContext……脑壳疼。
- 页面越写越臃肿,最后自己都找不到哪段是干啥的……
别慌!今天我们就来聊聊 React 中最基础、也最容易被忽视的核心概念之一:组件通信。
更重要的是——用乐高积木的方式,把页面“拼”出来!
🧩 1. 组件 = 乐高积木,页面 = 你的创意作品
想象一下:你小时候玩乐高,是不是先有一堆小零件(比如轮子、窗户、门),然后咔咔一拼,变成一辆车、一栋房子?
React 里的 组件(Component) 就是这些“乐高积木”:
- 最小开发单元:一个按钮、一张卡片、一个弹窗,都可以是一个组件。
- 可复用:写一次,到处用。比如
<Card />可以展示用户信息、商品详情、甚至猫猫照片! - 可嵌套:组件里还能放组件,就像乐高可以叠着拼。
// App.jsx —— 你是“乐高总指挥”
function App() {
return (
<div>
<Card className="user-card">
<h2>张三</h2>
<p>高级前端工程师</p>
<button>查看详情</button>
</Card>
</div>
)
}
而 Card 组件呢?它只关心“怎么展示”,不关心“展示谁”。这就是关注点分离的魔法!
📦 2. props:父组件给子组件的“快递包裹”
在 React 世界里,数据流动是单向的:从父到子,像一条单行道。
- state:组件自己的私有数据(比如用户输入、开关状态)。
- props:父组件“寄”给子组件的包裹,子组件只能“拆开看”,不能“修改退货”。
举个栗子🌰:
<Greeting name="cww" message="加入字节!!!" showIcon />
这个 <Greeting /> 组件收到三个“包裹”:
name:字符串message:字符串showIcon:布尔值(true/false)
子组件只需优雅地“签收”:
function Greeting({ name, message, showIcon }) {
return (
<div>
{showIcon && <span>👋</span>}
<h1>Hello {name}!</h1>
<p>{message}</p>
</div>
)
}
💡 小贴士:
props是只读的!如果你试图在子组件里修改它,React 会默默流泪(然后报错)。
🎁 3. 高级玩法:把“组件”当 props 传!
你以为 props 只能传字符串、数字?太天真了!
React 允许你传递整个组件!这叫 Render Props 或 组件作为 prop。
比如我们的 <Modal /> 弹窗:
<Modal
HeaderComponent={myHeader}
FooterComponent={myFooter}
>
<p>这是一个弹窗</p>
<p>你可以在这里显示任何JSX</p>
</Modal>
HeaderComponent和FooterComponent是两个函数组件。- 中间的
<p>...</p>是children—— React 的“隐藏彩蛋”。
在 Modal 内部:
const { HeaderComponent, FooterComponent, children } = props;
return (
<div style={styles.overlay}>
<div style={styles.modal}>
<HeaderComponent /> {/* 渲染头部 */}
<div style={styles.content}>{children}</div> {/* 渲染中间内容 */}
<FooterComponent /> {/* 渲染底部 */}
</div>
</div>
)
✨ 这招让组件高度可定制!同一个 Modal,可以变出 100 种样式,老板看了直呼“内卷之王”!
🔍 4. 类型安全?PropTypes 来护航!
JavaScript 很自由,但自由过头就容易翻车。比如:
<Greeting name={123} /> // name 居然是数字??
这时候,PropTypes 就像组件的“安检员”:
import PropTypes from 'prop-types';
Greeting.propTypes = {
name: PropTypes.string.isRequired, // 必须是字符串,且必传!
message: PropTypes.string, // 字符串,可选
showIcon: PropTypes.bool // 布尔值
}
// 注意:default 不是这样写的!正确方式是 defaultProps
Greeting.defaultProps = {
message: "欢迎加入!"
}
⚠️ 虽然现在 TypeScript 更流行,但在纯 JS 项目中,PropTypes 依然是守护神!
💡 5. 思考:为什么 React 要这样设计?
React 强调 单向数据流,看似限制多,实则大智慧:
- 可预测性:数据从哪来、到哪去,一目了然。
- 调试友好:出 bug 时,顺着 props 链就能定位。
- 组件解耦:子组件不依赖父组件的具体实现,只认“接口”(props)。
就像乐高说明书:每一步该拼哪块,清清楚楚。你不会把轮子装到屋顶上(除非你想造飞车🚗)。
🎉 结语:做一名“乐高架构师”
React 的魅力,不在于炫技,而在于用简单规则构建复杂系统。
下次写组件时,不妨问自己:
- 这个组件能不能像乐高一样被复用?
- 它需要哪些“props 包裹”才能工作?
- 能不能把 UI 拆得更小、更纯粹?
记住:好的 React 开发者,不是写代码最多的人,而是写组件最“懒”的人——因为他们的组件,早就被复用了 100 次!