` container. For example, let's say the parent component passes three `
` 包裹了接收到的每一个子元素。举个例子,假设父组件将三个 `
` 作为 `children` 属性传递给 `RowList`:
```js
- This is the first item.
- This is the second item.
- This is the third item.
+ 这是第一项。
+ 这是第二项。
+ 这是第三项。
```
-Then, with the `RowList` implementation above, the final rendered result will look like this:
+然后,使用实现上面的 `RowList`,最终的渲染结果将是像下面这样:
```js
-
This is the first item.
+
这是第一项。
-
This is the second item.
+
这是第二项。
-
This is the third item.
+
这是第三项。
```
-`Children.map` is similar to [to transforming arrays with `map()`.](/learn/rendering-lists) The difference is that the `children` data structure is considered *opaque.* This means that even if it's sometimes an array, you should not assume it's an array or any other particular data type. This is why you should use `Children.map` if you need to transform it.
+`Children.map` 和 [用来转化数组的 `map()` 类似](/learn/rendering-lists)。区别在于 `children` 被视为 **不透明的**。这意味着即使有时它真的是一个数组,你也不应该假设它是一个数组或者其他数据类型。这就是为什么如果你要转换`children`, 应该使用 `Children.map`。
@@ -250,9 +250,9 @@ import RowList from './RowList.js';
export default function App() {
return (
- This is the first item.
- This is the second item.
- This is the third item.
+ 这是第一项。
+ 这是第二项。
+ 这是第三项。
);
}
@@ -293,24 +293,24 @@ export default function RowList({ children }) {
-#### Why is the children prop not always an array? {/*why-is-the-children-prop-not-always-an-array*/}
+#### 为什么 children 属性并不总是一个数组? {/*why-is-the-children-prop-not-always-an-array*/}
-In React, the `children` prop is considered an *opaque* data structure. This means that you shouldn't rely on how it is structured. To transform, filter, or count children, you should use the `Children` methods.
+在 React 中,`children` 属性是被视为 **不透明的** 数据结构。这意味着你不应该依赖它的结构。如果要转换,过滤,或者统计子节点,你应该使用 `Children` 方法。
-In practice, the `children` data structure is often represented as an array internally. However, if there is only a single child, then React won't create an extra array since this would lead to unnecessary memory overhead. As long as you use the `Children` methods instead of directly introspecting the `children` prop, your code will not break even if React changes how the data structure is actually implemented.
+实际操作过程中,`children` 在底层常常被表示为数组。但是如果这里只有一个子节点,那么 React 将不会创建数组,因为这将导致不必要的内存开销。只要你使用 `Children` 方法而不是直接操作 `children` 底层结构,即使 React 改变了 `children` 数据结构的实际实现方式,你的代码也不会被中断。
-Even when `children` is an array, `Children.map` has useful special behavior. For example, `Children.map` combines the [keys](/learn/rendering-lists#keeping-list-items-in-order-with-key) on the returned elements with the keys on the `children` you've passed to it. This ensures the original JSX children don't "lose" keys even if they get wrapped like in the example above.
+当 `children` 是一个数组时,`Children.map` 会有许多有用的特性。比如,`Children.map` 将被返回元素上的 [key](/learn/rendering-lists#keeping-list-items-in-order-with-key) 和 你传递给它的 `children` 上的 key 绑定。这保证了原本的 JSX 子元素不会“丢失” key,即使它们上面的例子中那样被包裹。
-The `children` data structure **does not include rendered output** of the components you pass as JSX. In the example below, the `children` received by the `RowList` only contains two items rather than three:
+`children` 的数据结构中 **不会包括你传递的 JSX 组件的渲染输出结果**。在下面的例子中,`RowList` 接收到的 `children` 仅包含两个子项而不是三个:
-1. `This is the first item.
`
+1. `这是第一项。
`
2. ``
-This is why only two row wrappers are generated in this example:
+这就是为什么在这个例子中仅产生了两个行级元素容器。
@@ -320,7 +320,7 @@ import RowList from './RowList.js';
export default function App() {
return (
- This is the first item.
+ 这是第一项。
);
@@ -329,8 +329,8 @@ export default function App() {
function MoreRows() {
return (
<>
- This is the second item.
- This is the third item.
+ 这是第二项。
+ 这是第三项。
>
);
}
@@ -369,15 +369,15 @@ export default function RowList({ children }) {
-**There is no way to get the rendered output of an inner component** like `` when manipulating `children`. This is why [it's usually better to use one of the alternative solutions.](#alternatives)
+当操作 `children` 时,我们没办法获取到像 `` 这样的内部组件的渲染输出结果,这就是为什么 [我们更推荐使用替代方案之一](#alternatives)。
---
-### Running some code for each child {/*running-some-code-for-each-child*/}
+### 为每一个子元素执行一段代码 {/*running-some-code-for-each-child*/}
-Call `Children.forEach` to iterate over each child in the `children` data structure. It does not return any value and is similar to the [array `forEach` method.](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) You can use it to run custom logic like constructing your own array.
+调用 `Children.forEach` 能够迭代 `children` 数据结构中的每一个子节点。它并不会返回任何值,这和 [数组的 `forEach` 方法](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) 类似。你可以使用它来运行自定义逻辑,例如构造自己的数组。
@@ -387,9 +387,9 @@ import SeparatorList from './SeparatorList.js';
export default function App() {
return (
- This is the first item.
- This is the second item.
- This is the third item.
+ 这是第一项。
+ 这是第二项。
+ 这是第三项。
);
}
@@ -413,15 +413,15 @@ export default function SeparatorList({ children }) {
-As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating `children`. This is why [it's usually better to use one of the alternative solutions.](#alternatives)
+就像之前提到过的一样,当操作 `children` 时,我们没办法获取到内部组件的渲染输出结果。这就是为什么 [我们更推荐使用替代方案之一](#alternatives)。
---
-### Counting children {/*counting-children*/}
+### 统计子节点 {/*counting-children*/}
-Call `Children.count(children)` to calculate the number of children.
+调用 `Children.count(children)` 能够计算子节点的数量。
@@ -431,9 +431,9 @@ import RowList from './RowList.js';
export default function App() {
return (
- This is the first item.
- This is the second item.
- This is the third item.
+ 这是第一项。
+ 这是第二项。
+ 这是第三项。
);
}
@@ -484,15 +484,15 @@ export default function RowList({ children }) {
-As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating `children`. This is why [it's usually better to use one of the alternative solutions.](#alternatives)
+就像之前提到过的一样,当操作 `children`时,我们没办法获取到内部组件的渲染输出结果。这就是为什么 [我们更推荐使用替代方案之一](#alternatives)。
---
-### Converting children to an array {/*converting-children-to-an-array*/}
+### 将 children 转化为数组 {/*converting-children-to-an-array*/}
-Call `Children.toArray(children)` to turn the `children` data structure into a regular JavaScript array. This lets you manipulate the array with built-in array methods like [`filter`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), [`sort`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), or [`reverse`.](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)
+通过调用 `Children.toArray(children)` 将 `children` 变为一个常规的 JavaScript 数组。这使得你能够使用 [`filter`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), [`sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), 或者 [`reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse) 等数组内置方法来操作这个数组。
@@ -502,9 +502,9 @@ import ReversedList from './ReversedList.js';
export default function App() {
return (
- This is the first item.
- This is the second item.
- This is the third item.
+ 这是第一项。
+ 这是第二项。
+ 这是第三项。
);
}
@@ -524,31 +524,31 @@ export default function ReversedList({ children }) {
-As mentioned earlier, there is no way to get the rendered output of an inner component when manipulating `children`. This is why [it's usually better to use one of the alternative solutions.](#alternatives)
+就像之前提到过的一样,当操作 `children`时,我们没办法获取到内部组件的渲染输出结果。这就是为什么 [我们更推荐使用替代方案之一](#alternatives)。
---
-## Alternatives {/*alternatives*/}
+## 替代方案 {/*alternatives*/}
-This section describes alternatives to the `Children` API (with capital `C`) that's imported like this:
+像下面这样导入的就是(大写字母 `C` 开头的)`Children` API,本章节将会介绍它的一些替代方案:
```js
import { Children } from 'react';
```
-Don't confuse it with [using the `children` prop](/learn/passing-props-to-a-component#passing-jsx-as-children) (lowercase `c`), which is good and encouraged.
+不要将它和 (小写字母 `c` 开头的) [`children` 属性](/learn/passing-props-to-a-component#passing-jsx-as-children) 混淆,后者是我们推荐使用的。
-### Exposing multiple components {/*exposing-multiple-components*/}
+### 暴露多个组件 {/*exposing-multiple-components*/}
-Manipulating children with the `Children` methods often leads to fragile code. When you pass children to a component in JSX, you don't usually expect the component to manipulate or transform the individual children.
+使用 `Children` 方法操作子节点通常会削弱代码的健壮性。在 JSX 中将子节点传递给组件时,通常不希望操作或转换子节点。
-When you can, try to avoid using the `Children` methods. For example, if you want every child of `RowList` to be wrapped in ``, export a `Row` component, and manually wrap every row into it like this:
+如果能够的话,尽量避免使用 `Children` 方法。例如,如果你希望 `RowList` 的每一个子节点都被 `
` 包裹,那么可以导出一个 `Row` 组件,然后像下面这样手动把包裹每一行:
@@ -559,13 +559,13 @@ export default function App() {
return (
- This is the first item.
+ 这是第一项。
- This is the second item.
+ 这是第二项。
- This is the third item.
+ 这是第三项。
);
@@ -607,7 +607,7 @@ export function Row({ children }) {
-Unlike using `Children.map`, this approach does not wrap every child automatically. **However, this approach has a significant benefit compared to the [earlier example with `Children.map`](#transforming-children) because it works even if you keep extracting more components.** For example, it still works if you extract your own `MoreRows` component:
+和使用 `Children.map` 不同,这种方式不会自动包裹每个子节点。但是,和 [上文中关于 `Children.map` 例子](#transforming-children) 相比,这种方式具有明显的优势,因为即使你继续抽离更多的组件,它也仍然有效。
@@ -618,7 +618,7 @@ export default function App() {
return (
- This is the first item.
+ 这是第一项。
@@ -629,10 +629,10 @@ function MoreRows() {
return (
<>
- This is the second item.
+ 这是第二项。
- This is the third item.
+ 这是第三项。
>
);
@@ -674,13 +674,13 @@ export function Row({ children }) {
-This wouldn't work with `Children.map` because it would "see" `
` as a single child (and a single row).
+这里使用 `Children.map` 得不到一样的结果,因为它会“认为” `
` 只是一个单独的子节点(并且只占据了一行)。
---
-### Accepting an array of objects as a prop {/*accepting-an-array-of-objects-as-a-prop*/}
+### 接收对象数组作为参数 {/*accepting-an-array-of-objects-as-a-prop*/}
-You can also explicitly pass an array as a prop. For example, this `RowList` accepts a `rows` array as a prop:
+你也可以显示地传递一个数组作为组件的参数。例如,下面的 `RowList` 接收了一个 `rows` 数组作为组件的参数:
@@ -690,9 +690,9 @@ import { RowList, Row } from './RowList.js';
export default function App() {
return (
This is the first item. },
- { id: 'second', content: This is the second item.
},
- { id: 'third', content: This is the third item.
}
+ { id: 'first', content: 这是第一项。
},
+ { id: 'second', content: 这是第二项。
},
+ { id: 'third', content: 这是第三项。
}
]} />
);
}
@@ -729,9 +729,9 @@ export function RowList({ rows }) {
-Since `rows` is a regular JavaScript array, the `RowList` component can use built-in array methods like [`map`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map) on it.
+因为 `rows` 是一个常规的 JavaScript 数组,`RowList` 组件可以对其使用 [`map`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 等数组内置方法。
-This pattern is especially useful when you want to be able to pass more information as structured data together with children. In the below example, the `TabSwitcher` component receives an array of objects as the `tabs` prop:
+当你希望能够将更多信息作为结构化数据,与子节点一起传递时,这个方案将会非常有用。在下面的示例中,`TabSwitcher` 接收了一个对象数组作为 `tabs` 的属性:
@@ -744,17 +744,17 @@ export default function App() {
{
id: 'first',
header: 'First',
- content: This is the first item.
+ content: 这是第一项。
},
{
id: 'second',
header: 'Second',
- content: This is the second item.
+ content: 这是第二项。
},
{
id: 'third',
header: 'Third',
- content: This is the third item.
+ content: 这是第三项。
}
]} />
);
@@ -789,13 +789,13 @@ export default function TabSwitcher({ tabs }) {
-Unlike passing the children as JSX, this approach lets you associate some extra data like `header` with each item. Because you are working with the `tabs` directly, and it is an array, you do not need the `Children` methods.
+和将子节点作为 JSX 传递不同,这个方法允许你将一些额外的数据,比如 `header`,与每个子项关联。因为你直接使用 `tabs`,并且它是一个数组,所以你并不需要 `Children` 方法。
---
-### Calling a render prop to customize rendering {/*calling-a-render-prop-to-customize-rendering*/}
+### 调用渲染属性以自定义渲染 {/*calling-a-render-prop-to-customize-rendering*/}
-Instead of producing JSX for every single item, you can also pass a function that returns JSX, and call that function when necessary. In this example, the `App` component passes a `renderContent` function to the `TabSwitcher` component. The `TabSwitcher` component calls `renderContent` only for the selected tab:
+除了为每一个子项生成 JSX,你还可以传递一个返回值类型是 JSX 的函数,并且在必要的时候调用这个函数。在这个示例中,`App` 组件向 `TabSwitcher` 组件传递了一个 `renderContent` 函数。`TabSwitcher` 组件仅对被选中的 tab 调用 `renderContent`。
@@ -844,9 +844,9 @@ export default function TabSwitcher({ tabIds, getHeader, renderContent }) {
-A prop like `renderContent` is called a *render prop* because it is a prop that specifies how to render a piece of the user interface. However, there is nothing special about it: it is a regular prop which happens to be a function.
+像 `renderContent` 这样的参数会被称为渲染属性,因为它指定了如何渲染一部分用户交互界面。但是,它也并没有什么特别之处,只是一个普通的属性同时恰好又是一个函数。
-Render props are functions, so you can pass information to them. For example, this `RowList` component passes the `id` and the `index` of each row to the `renderRow` render prop, which uses `index` to highlight even rows:
+渲染属性是函数,所以你可以向它们传递参数。比如,这里的 `RowList` 组件向 `renderRow` 传递了一个 `id` 和每一行的 `index`,该属性用 `index` 来选择偶数行:
@@ -927,23 +927,23 @@ export function Row({ children, isHighlighted }) {
-This is another example of how parent and child components can cooperate without manipulating the children.
+这是如何在不操纵子组件的情况下,父组件和子组件进行协作的另一个示例。
---
-## Troubleshooting {/*troubleshooting*/}
+## 错误排查 {/*troubleshooting*/}
-### I pass a custom component, but the `Children` methods don't show its render result {/*i-pass-a-custom-component-but-the-children-methods-dont-show-its-render-result*/}
+### 我传递入了一个自定义组件,但是 `Children` 方法没有显示渲染的内容 {/*i-pass-a-custom-component-but-the-children-methods-dont-show-its-render-result*/}
-Suppose you pass two children to `RowList` like this:
+假设你向 `RowList` 传入了两个子节点,像下面这样:
```js
- First item
+ 第一项
```
-If you do `Children.count(children)` inside `RowList`, you will get `2`. Even if `MoreRows` renders 10 different items, or if it returns `null`, `Children.count(children)` will still be `2`. From the `RowList`'s perspective, it only "sees" the JSX it has received. It does not "see" the internals of the `MoreRows` component.
+如果你在 `RowList` 中执行 `Children.count(children)`,其返回值将为 `2`。即使 `MoreRows` 渲染了 10 个不同的子项,或者返回了 `null`,`Children.count(children)` 的返回值仍然是 `2`。从 `RowList` 的角度上看,它只能感知到它直接接收到的 JSX,并不能感知到 `MoreRows` 组件的内部。
-The limitation makes it hard to extract a component. This is why [alternatives](#alternatives) are preferred to using `Children`.
+这导致抽离一个组件变得较为困难,这也是为什么我们更推荐使用 [替代方案](#alternatives) 而不是使用 `Children`。