agentmentoragentmentor

第 03 节:Props:让同一个组件显示不同数据

本节 objectives:

  • 能用 props 给组件传入文本、数字和布尔值。
  • 能区分父组件传 props 和子组件读取 props。
  • 能用 children 组合一块可包裹内容的组件。

先修:组件和 JSX | 上一节 << 02 | 下一节 04 >>

复用组件的第一步不是复制,而是给它入口

如果 ProfileCard 只能显示 Ada,你会很快复制出 LinCardMinaCard。React 里更自然的做法是把会变化的数据作为 props 传进去。官方文档把 props 描述为父组件传给子组件的信息,子组件像读取函数参数一样读取它们。1

props 解决的是"同一种形状,不同数据"。

讲解

父组件传 props:

jsx
function Team() {  return (    <>      <ProfileCard name="Ada" role="Designer" />      <ProfileCard name="Lin" role="Engineer" />    </>  );}

子组件读取 props:

jsx
function ProfileCard({ name, role }) {  return (    <article>      <h2>{name}</h2>      <p>{role}</p>    </article>  );}

字符串可以直接写在引号里。数字、布尔值、对象和数组通常放在大括号里:

jsx
<Progress done={3} total={7} compact={true} />

props 是只读输入。子组件不应该改 props;如果界面需要随用户操作变化,那会进入下一节的 state。

children 是一种特殊 props,表示组件标签中间夹着的内容:

jsx
function Panel({ title, children }) {  return (    <section>      <h2>{title}</h2>      {children}    </section>  );}

跟我做一遍(worked example)

需求:做三张课程任务卡,标题和状态不同,卡片结构相同。

jsx
function TaskCard({ title, status }) {  return (    <article>      <h3>{title}</h3>      <p>{status}</p>    </article>  );}
function TaskList() {  return (    <section>      <TaskCard title="写第一个组件" status="已完成" />      <TaskCard title="练 JSX" status="进行中" />      <TaskCard title="传 props" status="未开始" />    </section>  );}

为什么这样做:任务卡的视觉形状稳定,变化的是数据。props 把变化点暴露出来,组件本身不需要知道数据来自哪里。

换你补全(faded example)

补全一个可包裹任意内容的 Notice 组件:

jsx
function Notice({ type, ________ }) {  return (    <aside className={`notice notice-${type}`}>      ________    </aside>  );}
function Page() {  return (    <Notice type="tip">      <p>先让组件跑起来,再拆 props。</p>    </Notice>  );}

参考答案:

jsx
function Notice({ type, children }) {  return (    <aside className={`notice notice-${type}`}>      {children}    </aside>  );}

关键判断是这里不该传一个固定 message 字符串。childrenNotice 能包裹段落、列表或按钮。

小结 + 通向下一节

props 让父组件把数据交给子组件。它适合外部输入,不适合保存用户操作后的变化。

下一节进入 state 和事件:组件终于能记住"刚才发生了什么"。

Footnotes

  1. Passing Props to a Component — https://react.dev/learn/passing-props-to-a-component

练习

Level 1: 写一个 ProductCard 组件,接收 namepriceinStock 三个 props。

提示 1

props 传"数据"。

提示 2

children 传"一块 UI"。

提示 3

如果你想传多个互相关联的标签,优先想想 children。

自评