JSX 中的孩子们

在包含开始标记和结束标记的 JSX 表达式中,这些标记之间的内容作为特殊 prop:props.children 传递。通过孩子有几种不同的方法:

字符串文字

你可以在开始和结束标签之间放一个字符串,props.children 就是那个字符串。这对许多内置 HTML 元素很有用。例如:

<MyComponent>
    <h1>Hello world!</h1>
</MyComponent>

这是有效的 JSX,MyComponent 中的 props.children 只是 <h1>Hello world!</h1>

请注意, HTML 未转义,因此你通常可以像编写 HTML 一样编写 JSX。

请记住,在这种情况下 JSX:

  • 删除行开头和结尾的空格;
  • 删除空白行;
  • 删除与标签相邻的新行;
  • 在字符串文字中间出现的新行被压缩到一个空格中。

JSX 儿童

你可以提供更多 JSX 元素作为子项。这对于显示嵌套组件很有用:

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

你可以将不同类型的子项混合在一起,因此你可以将字符串文字与 JSX 子项一起使用。这是 JSX 与 HTML 类似的另一种方式,因此这是有效的 JSX 和有效的 HTML:

<div>
  <h2>Here is a list</h2>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
</div>

请注意,React 组件不能返回多个 React 元素,但单个 JSX 表达式可以有多个子元素。因此,如果你希望组件呈现多个内容,你可以将它们包装在 div 中,如上例所示。

JavaScript 表达式

你可以将任何 JavaScript 表达式作为子项传递,方法是将其包含在 {} 中。例如,这些表达式是等效的:

<MyComponent>foo</MyComponent>

<MyComponent>{'foo'}</MyComponent>

这通常用于呈现任意长度的 JSX 表达式列表。例如,这会呈现一个 HTML 列表:

const Item = ({ message }) => (
  <li>{ message }</li>
);

const TodoList = () => {
  const todos = ['finish doc', 'submit review', 'wait stackoverflow review'];
  return (
    <ul>
      { todos.map(message => (<Item key={message} message={message} />)) }
    </ul>
  );
};

请注意,JavaScript 表达式可以与其他类型的子项混合使用。

作为儿童的功能

通常,在 JSX 中插入的 JavaScript 表达式将计算为字符串,React 元素或这些事物的列表。然而,props.children 就像任何其他道具一样,它可以传递任何类型的数据,而不仅仅是 React 知道如何渲染的类型。例如,如果你有自定义组件,则可以将其作为 props.children 进行回调:

const ListOfTenThings = () => (
  <Repeat numTimes={10}>
    {(index) => <div key={index}>This is item {index} in the list</div>}
  </Repeat>
);

// Calls the children callback numTimes to produce a repeated component
const Repeat = ({ numTimes, children }) => {
  let items = [];
  for (let i = 0; i < numTimes; i++) {
    items.push(children(i));
  }
  return <div>{items}</div>;
};

传递给自定义组件的子代可以是任何东西,只要该组件将它们转换为 React 在渲染之前可以理解的内容。这种用法并不常见,但如果你想扩展 JSX 的功能,它就有用了。

忽略的值

请注意,falsenullundefinedtrue 是有效的孩子。但他们根本就没有渲染。这些 JSX 表达式将呈现相同的东西:

<MyComponent />

<MyComponent></MyComponent>

<MyComponent>{false}</MyComponent>

<MyComponent>{null}</MyComponent>

<MyComponent>{true}</MyComponent>

这对于有条件地呈现 React 元素非常有用。这个 JSX 只渲染 if showHeader 为真:

<div>
  {showHeader && <Header />}
  <Content />
</div>

一个重要的警告是,一些假的值,例如 0 号,仍然由 React 呈现。例如,此代码的行为不会像你预期的那样,因为当 props.messages 为空数组时将打印 0

<div>
  {props.messages.length &&
    <MessageList messages={props.messages} />
  }
</div>

解决此问题的一种方法是确保 && 之前的表达式始终为 boolean:

<div>
  {props.messages.length > 0 &&
    <MessageList messages={props.messages} />
  }
</div>

最后,请记住,如果你希望输出中出现 falsetruenullundefined 等值,则必须先将其转换为字符串:

<div>
  My JavaScript variable is {String(myVariable)}.
</div>