Skip to content
This page has been auto-translated and may contain errors.View in English

Props

假设你在构建一个 Greeting 组件用于欢迎横幅,每个登录的访客都需要看到自己的名字而不是硬编码的同一个名字。一个只能渲染单一固定值的组件无法独立完成这件事。Props(属性的简称)是你从外部向组件传递数据的方式,就像函数参数向函数传递值一样。你在组件上写 props 的方式和在 HTML 标签上写属性一样,组件通过一个参数读取这些 props。

jsx
function Greeting({ name }) {
  return <h1>Hello, {name}</h1>
}
// 使用方式: <Greeting name="Ada" />

Greeting 接收一个 prop,叫 name。React 会把你在 <Greeting> 上写的所有属性收集到一个对象里,然后把这个对象作为组件的第一个参数传递给它,所以这里的 { name } 是在解构这个对象,直接提取出 name 的值。调用 <Greeting name="Ada" /> 时,函数内部 name 就是 "Ada"。用不同的名字再调用一次,你就能从同一个组件得到不同的标题。

Props 是单向流动的:从使用组件的地方,流向组件内部。在 Greeting 里,name 表现得像一个普通变量,但组件无法改变它:props 是只读的。如果一个组件需要随时间变化的数据,那就需要用到 state,我们会在后面的章节讲到。

默认值

如果某个 prop 可能缺失,可以用给函数参数设置默认值的同样方式给它设置默认值:在解构模式中使用 =

jsx
function Greeting({ name = 'friend' }) {
  return <h1>Hello, {name}</h1>
}

调用 <Greeting /> 时不传 name prop,name 就会回退到 'friend'。如果传了 name,它会覆盖默认值。这就是普通的 JavaScript 默认参数语法,应用到 React 传给组件的对象上而已。

children prop

有些组件需要包裹其他内容,而不是通过属性接收内容。把内容写在组件的开标签和闭标签之间,React 会自动将其作为一个特殊的 children prop 传递进来。

jsx
function Card({ children }) {
  return <div className="card">{children}</div>
}

// 使用方式:
// <Card>
//   <p>放在这里的任何内容都会成为 Card 的 children prop。</p>
// </Card>

children 的用法和任何其他 prop 完全一样:你通过同样的解构参数读取它,组件决定在哪里渲染它。唯一的区别是它的传递方式,通过标签的内容而不是命名属性。

传递任何 JavaScript 值

Props 可以接收任何 JavaScript 值:数字、布尔值、对象、数组,甚至函数。把值用花括号包裹起来,而不是用引号。

jsx
function UserCard({ user, onSelect }) {
  return <button onClick={() => onSelect(user.id)}>{user.name}</button>
}

// 使用方式: <UserCard user={{ id: 1, name: '李明' }} onSelect={handleSelect} />

这里 user 是一个对象,onSelect 是一个传递下来的函数,组件可以调用它。当有人点击按钮时,onClick 会执行 onSelect,这是一个事件处理器,Events 章节会详细讲解;现在你就暂时相信它的作用。这就是组件之间的通信方式:数据通过 props 向下流动,行为也是以函数的形式沿着同样的方向向下传递,子组件可以调用这个函数。

单向数据流

Props 在组件树中有意识地单向流动。父组件向子组件传递数据,子组件可以继续向下传递,但没有东西通过 props 流向上方。组件绝不能写入自己的 props 对象,也不能改变通过 prop 接收到的对象或数组;你接收到的一切都应该视为固定的。

这个约束是为了保持渲染的可预测性。当某处的 state 改变并且 React 重新渲染受影响的组件时,每次重新渲染都会根据该组件当前的 props 和 state 重新计算其 JSX。如果组件可以向上改变父组件给它的 props,父组件就会失去对自己数据的可靠认识,调试 bug 时就需要检查值经过的每个子组件,而不是检查它实际改变的那唯一的地方。保持 props 只读能让这一切可追踪:你 UI 中的任何值都恰好有一个地方设置它。

Props 是把数据传入组件的方式。再过几章,state 会讲解组件如何保持并随时间更新自己的数据。

JunoProps 是只读的 Props 是组件从使用者那里接收信息的方式,就像函数参数给函数传值一样。你从解构参数读取 props,比如 { name },组件永远不会改变它接收到的 props。

当某个 prop 可能缺失时,用 = 给它设置默认值,别忘了组件标签之间的任何内容都会作为 children prop 到达组件。

JunoProps 是只读的 Props 是组件的输入:从参数中解构它们,对可能缺失的 prop 设置默认值,把 children 当作另一个 prop,它恰好通过标签内容而不是属性到达。

Props 可以接收任何东西,字符串、对象、函数,所以用它们来一起传递数据和行为。不要改变你接收到的东西;props 始终保持只读。

JunoProps 是只读的 Props 单向流向下方,这个方向是至关重要的:改变自己 props 的组件会破坏"渲染反映已知输入"这个保证。

默认参数和 children 是普通的 JavaScript 和 JSX 语法,建立在一个简单对象之上。在组件端保持 props 不可变,渲染就能保持可预测,这正是你在 React 其他地方依赖的特性。

接下来:列表和 keys,在这里一个组件会渲染整个数据数组。