向组件传递 Props:数据传递、默认值与 children 嵌套
React 组件使用 props(属性 properties 的缩写)进行相互通信。每一个父组件都可以通过给子组件传递 props,把数据一层层流淌下去。
Props 可以传递任何 JavaScript 值:包括数字、字符串、对象、数组,甚至是完整的 JSX 元素和函数!
1. 熟悉的生活比喻:Props 就是函数的参数
如果你熟悉 JavaScript 函数:
function add(a, b) {
return a + b;
}
add(2, 3); // 传入参数 2 和 3
在 React 里:
function Avatar({ person, size }) { ... }
<Avatar person={{ name: 'Lin' }} size={100} /> // 传入参数 person 和 size
组件就是函数,Props 就是传入函数的唯一参数对象!
2. 传递并读取 Props 的两步法
步骤一:向子组件传递 props
在父组件调用子组件时,像写 HTML 属性一样传值:
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
步骤二:在子组件内部读取 props
在子组件的函数签名中,React 会把所有传入的属性打包成一个对象作为第一个参数传入。我们可以使用现代 JavaScript 的 解构赋值(Destructuring) 直接拿到所需的属性:
function Avatar({ person, size }) {
// 直接使用 person 和 size
const imageUrl = `https://i.imgur.com/${person.imageId}.jpg`;
return (
<img
className="avatar"
src={imageUrl}
alt={person.name}
width={size}
height={size}
/>
);
}
3. 为 Prop 指定默认值(Default Value)
有时调用方可能没有传入某个 prop,或者传入了 undefined。为了避免组件崩溃或样式错乱,你可以在解构时直接为其赋予默认值:
function Avatar({ person, size = 100 }) {
// 如果没有传入 size,size 就会默认等于 100
// ...
}
注意:默认值仅在该属性缺失或者传入了
undefined时才会生效。如果调用方显式传入了size={null}或size={0},默认值不会生效。
4. 特殊的 Prop:将 JSX 作为 children 传递
在 HTML 中,我们经常将一个标签嵌套在另一个标签内部:
<div>
<img />
<p>描述文本</p>
</div>
如果你想让自己的自定义组件也支持这种嵌套语法,例如实现一个可复用的白色卡片包装器 <Card>:
<Card>
<Avatar person={...} />
<h2>科学家介绍</h2>
</Card>
在 Card 组件内部,包裹在开闭标签中间的所有内容,都会自动作为名为 children 的 prop 注入进来!
function Card({ children }) {
return (
<div className="card-box" style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '20px',
margin: '10px',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
}}>
{children}
</div>
);
}
Card 组件根本不需要关心它的肚子里塞的是图片、文字还是表单,它只负责提供统一的卡片外壳,并把 {children} 渲染在其中。这是构建通用 UI 库时最为强大的设计模式!
5. Props 是不可变的只读快照!
在 React 中,Props 是只读的(Immutable)。
当组件想要根据用户交互改变界面时(例如点击后把 size 放大),千万不要尝试在子组件内部直接修改 props 的值:
// ❌ 绝对不要这样做!
function Avatar({ person, size }) {
size = size * 2; // 试图变异自身 props
// ...
}
为什么?
因为 Props 是父组件的财产。如果子组件直接篡改它,会导致父子组件数据产生严重割裂与不可预测的 bug。 如果需要改变数据,子组件应当通过事件通知父组件,由父组件更新自己的状态,并向子组件传递一份全新的 Props!
总结
- Props 是组件唯一的输入来源,等同于函数的参数;
- 使用解构语法
function MyComponent({ a, b = 默认值 })接收属性; childrenprop 让你能够像写原生 HTML 一样嵌套子节点,打造灵活的容器组件;- Props 是纯粹只读的,任何时候都不要试图在子组件内部修改它。