前言
在React中,组件接收到的props.children有多种类型:undefined、object、array。 通常情况下,我们基本不需要对props.children做特殊处理,但在某些情况下,比如将children的每个子元素包装在另一个元素/组件中,或者重新排序或切片它们。这种情况下,就需要用到React给我们提供的工具方法 React.Children。
以下是基本用法:
function Parent({ children }) { return <div className="mt-10">{children}</div>; } 复制代码
如果需要对children进行加强(一个常见的用例是将迭代索引相关信息传递给父组件的子组件):
import { Children, cloneElement } from "react"; function Breadcrumbs({ children }) { const arrayChildren = Children.toArray(children); return ( <ul style={{ listStyle: "none", display: "flex", }} > {Children.map(arrayChildren, (child, index) => { const isLast = index === arrayChildren.length - 1; if (! isLast && ! child.props.link ) { throw new Error( `BreadcrumbItem child no. ${index + 1} should be passed a 'link' prop` ) } return ( <> {child.props.link ? ( <a href={child.props.link} style={{ display: "inline-block", textDecoration: "none", }} > <div style={{ marginRight: "5px" }}> {cloneElement(child, { isLast, })} </div> </a> ) : ( <div style={{ marginRight: "5px" }}> {cloneElement(child, { isLast, })} </div> )} {!isLast && ( <div style={{ marginRight: "5px" }}> > </div> )} </> ); })} </ul> ); } function BreadcrumbItem({ isLast, children }) { return ( <li style={{ color: isLast ? "black" : "blue", }} > {children} </li> ); } export default function App() { return ( <Breadcrumbs> <BreadcrumbItem link="https://goibibo.com/" > Goibibo </BreadcrumbItem> <BreadcrumbItem link="https://goibibo.com/hotels/" > Hotels </BreadcrumbItem> <BreadcrumbItem> A Fancy Hotel Name </BreadcrumbItem> </Breadcrumbs> ); } 复制代码
网络异常,图片无法展示
|
说明:
- 使用
React.Children.toArray
确保children
是一个数组。因为组件接收到的children
属性可能是对象、数组,甚至是一个函数,如果在代码里我们直接使用children.map
方法,就会报错。 - 在
Breadcrumbs
父组件中,我们使用实用方法遍历它的子组件React.Children.map
- 通过访问
index
迭代器函数内部(回调函数的第二个参数React.Children.map
),检测持否是最后一个子节点 - 如果是最后一个子节点,就克隆元素并将
isLast
属性传递给它,以便子元素可以根据它设置自己的样式。 - 如果不是最后一个子节点,我们确保所有不是最后一个孩子的孩子都有一个
link
道具,如果他们没有就抛出一个错误。我们像第 4 步一样克隆元素,并isLast
像之前一样传递 prop,但我们还额外将这个克隆的元素包装在锚标记中。
www.smashingmagazine.com/2021/08/rea…