子元素(Children)
Children
允许你操作和转换作为
children
属性
接收到的 JSX。
const
mappedChildren = Children.map(children, child =>
<div className="Row">
{child}
</div>
);
Children.count(children)
调用
Children.count(children)
来计算
children
数据结构中的子元素数量。
import { Children } from 'react';
function RowList({ children }) {
return (
<>
<h1>Total rows: {Children.count(children)}</h1>
...
</>
);
}
children
: 你的组件收到的
children
属性
的值。
这些
children
内的节点数量。
null
、
undefined
和布尔值)、字符串、数字和
React 元素
计为单个节点。数组不计为单个节点,但其子元素计为单个节点。
遍历不会深入到 React 元素中:
它们不会被渲染,它们的子元素也不会被遍历。
碎片
不会被遍历。
Children.forEach(children, fn, thisArg?)
调用
Children.forEach(children, fn, thisArg?)
对
children
数据结构中的每个子元素运行一些代码。
import { Children } from 'react';
function SeparatorList({ children }) {
const result = [];
Children.forEach(children, (child, index)
=> {
result.push(child);
result.push(<hr key={index} />);
});
// ...
Children.forEach(children, fn, thisArg?)
对
children
数据结构中的每个子元素运行一些代码。
import { Children } from 'react';
function SeparatorList({ children }) {
const result = [];
Children.forEach(children, (child, index)
=> {
result.push(child);
result.push(<hr key={index} />);
});
// ...
children
: 你的组件收到的
children
属性
的值。
fn
:您希望为每个子元素运行的函数,类似于
数组
forEach
方法
的回调函数。它将以子元素作为第一个参数,其索引作为第二个参数被调用。索引从
0
开始,每次调用递增。
thisArg
:
this
值
,
fn
函数应该以此值来调用。如果省略,则为
undefined
。
Children.forEach
返回
undefined
。
null
、
undefined
和布尔值)、字符串、数字和
React 元素
计为单个节点。数组不计为单个节点,但其子元素计为单个节点。
遍历不会深入到 React 元素中:
它们不会被渲染,它们的子元素也不会被遍历。
碎片
不会被遍历。
Children.map(children, fn, thisArg?)
调用
Children.map(children, fn, thisArg?)
对
children
数据结构中的每个子元素进行映射或转换。
import { Children } from 'react';
function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}
children
: 你的组件收到的
children
属性
的值。
fn
:映射函数,类似于
数组
map
方法
的回调函数。它将以子元素作为第一个参数,其索引作为第二个参数被调用。索引从
0
开始,每次调用递增。您需要从此函数返回一个 React 节点。这可以是空节点(
null
,
undefined
或布尔值)、字符串、数字、React 元素或其他 React 节点的数组。
thisArg
:
this
值
,
fn
函数应该以此值来调用。如果省略,则为
undefined
。
如果
children
为
null
或
undefined
,则返回相同的值。
否则,返回一个扁平数组,该数组包含您从
fn
函数返回的节点。返回的数组将包含您返回的所有节点,除了
null
和
undefined
。
空节点(
null
、
undefined
和布尔值)、字符串、数字和
React 元素
计为单个节点。数组不计为单个节点,但其子元素计为单个节点。
遍历不会深入到 React 元素中:
它们不会被渲染,它们的子元素也不会被遍历。
碎片
不会被遍历。
如果您从
fn
返回带有键的元素或元素数组,
则返回元素的键将自动与来自
children
的相应原始项的键合并。
当您从
fn
中以数组形式返回多个元素时,它们的键只需要在彼此之间局部唯一。
Children.only(children)
调用
Children.only(children)
来断言
children
代表单个 React 元素。
function Box({ children }) {
const element = Children.only(children);
// ...
children
: 你的组件收到的
children
属性
的值。
如果
children
是有效的元素
,则返回该元素。
否则,抛出错误。
Children.map
的返回值)作为
children
传递,则始终会
抛出异常。
换句话说,它强制要求
children
是单个 React 元素,而不是包含单个元素的数组。
Children.toArray(children)
调用
Children.toArray(children)
来根据
children
数据结构创建一个数组。
import { Children } from 'react';
export default function ReversedList({ children }) {
const result = Children.toArray(children);
result.reverse();
// ...
children
: 你的组件收到的
children
属性
的值。
返回
children
中元素的扁平数组。
null
、
undefined
和布尔值)将在返回的数组中被忽略。
返回元素的键将根据原始元素的键及其嵌套级别和位置计算。
这确保了扁平化数组不会改变行为。
转换子元素
要转换组件
作为
children
属性接收的子元素 JSX
,请调用
Children.map
import { Children } from 'react';
function RowList({ children }) {
return (
<div className="RowList">
{Children.map(children, child =>
<div className="Row">
{child}
</div>
)}
</div>
);
}
在上例中,
RowList
会将其接收到的每个子元素都包装在一个
<div className="Row">
容器中。例如,假设父组件传递三个
<p>
标签作为
children
属性传递给
RowList
<
RowList>
<p>This is the first item.</p>
<p>This is the second item.</p>
<p>This is the third item.</p>
</RowList>
然后,使用上面的
RowList
实现,最终渲染结果如下所示
<div className="RowList">
<div className="Row">
<p>This is the first item.</p>
</div>
<div className="Row">
<p>This is the second item.</p>
</div>
<div className="Row">
<p>This is the third item.</p>
</div>
</div>
Children.map
类似于
使用
map()
转换数组。
区别在于
children
数据结构被认为是 *不透明的*。这意味着即使它有时是数组,也不应该假设它是数组或任何其他特定数据类型。这就是为什么如果需要转换它,应该使用
Children.map
。
import { Children } from 'react'; export default function RowList({ children }) { return ( <div className="RowList"> {Children.map(children, child => <div className="Row"> {child} </div> </div>
深入探讨
在 React 中,
children属性被认为是不透明的数据结构。这意味着你不应该依赖它的结构。要转换、过滤或计数子元素,应该使用Children方法。实际上,
children数据结构通常在内部表示为数组。但是,如果只有一个子元素,那么 React 不会创建额外的数组,因为这会导致不必要的内存开销。只要使用Children方法而不是直接检查children属性,即使 React 更改了数据结构的实际实现方式,你的代码也不会中断。即使
children是一个数组,Children.map也有有用的特殊行为。例如,Children.map将返回元素上的 键 与你传递给它的children上的键组合起来。这确保了即使像上例一样被包装,原始的 JSX 子元素也不会“丢失”键。