Kodokon kodokon.com

组合:children 与拆分组件

利用 children 属性构建可复用的容器组件,并把你的界面拆分成职责清晰的部分。

6 分钟 · 3 题

在 Kodokon 中打开本课

有些组件事先并不知道自己的内容:一张卡片、一个模态窗口、一套布局。React 用特殊的 children 属性解决了这个问题:你放在一个组件开标签和闭标签之间的一切,都会交给它,随时可以插入到它想要的任何地方。容器负责框架,调用方提供内容。

JSX
function Card({ children }) {
  return <section className="card">{children}</section>;
}

function App() {
  return (
    <Card>
      <h2>Invoice #1024</h2>
      <p>Amount: €49.90</p>
    </Card>
  );
}
Card 为任意内容提供框架,而不需要知道它是什么。

当单一插槽不够用时,就通过具名 props 传入 JSX:一个标题、一个页脚、一个操作栏。一个 prop 可以像接收任何其他值一样接收一个 React 元素。你会得到多个“插槽”,每一个都有清晰的名字。

JSX
function Modal({ title, footer, children }) {
  return (
    <div className="modal">
      <header>{title}</header>
      <div className="modal-body">{children}</div>
      <footer>{footer}</footer>
    </div>
  );
}
三个不同的插槽:title、children 和 footer。

组合也指导着拆分。一个组件应当有一项可辨识的职责:显示一个用户行、排布一个列表。一旦某个组件积累了多种角色,就把它拆成子组件:每一个都变得更短、更易测试,并且能在别处复用。

JSX
function UserList({ users }) {
  return (
    <ul>
      {users.map((user) => (
        <UserRow key={user.id} user={user} />
      ))}
    </ul>
  );
}

function UserRow({ user }) {
  return (
    <li>
      <strong>{user.name}</strong> - {user.email}
    </li>
  );
}
每个组件都只保持一项职责。

知识检测

确认你已牢记本课的重点内容。

  1. 一个组件的 children 属性接收到的是什么?
    • 在同一文件中声明的它的子组件列表
    • 放在它开标签和闭标签之间的一切
    • 父组件向下传递的 props
  2. 你能通过 children 以外的 prop 来传递 JSX 吗?
    • 可以,一个 React 元素就是和其他值一样的值
    • 不行,只有 children 属性接受 JSX
    • 可以,但只能作为包含 HTML 的字符串
  3. 哪个信号最可靠地表明一个组件应该被拆分?
    • 它超过了二十行代码
    • 它使用了不止一个 useState
    • 它在渲染中把几项不同的职责组合在一起