今天所讲的Children,依旧是一个过时的API,在现在的开发中已经很少用到了,但是由于项目中依旧使用,所以就整理出了这个文章。
在介绍React.Children之前,先贴上在官网上的警告
使用 Children 的场景并不常见,使用它可能会削弱代码的健壮性。
简单点来说,当我们使用Children的时候,可能会被人怼。这也是为啥React不建议我们使用Children的原因,后面再来用例子解释下为啥不建议使用React.Children。
在介绍React.Children之前,先介绍一个很相似的API----props.children。防止大家混淆,所以先讲解下这个。
当我们想要将 JSX 作为子组件传递,或嵌套我们自己的组件的时候,我们可以在父组件中使用props.children获取到子组件。如下:
<div className="App">
<Pcomponent>
<Scomponent />
</Pcomponent>
</div>
在这例子中,我们创建了两个组件,也就是父组件和子组件,在结构上,父组件包含了子组件,而两个组件的内容如下:
function Pcomponent(props: any) {
return (
<div
style={{
border: "1px solid #000",
padding: "10px",
width: "fit-content",
}}
>
父组件
</div>
);
}
export default Pcomponent;
function Scomponent() {
return (
<div
style={{
border: "1px solid #000",
padding: "2px",
width: "fit-content",
marginTop: "10px",
}}
>
子组件
</div>
);
}
export default Scomponent;
页面效果如下:
很奇怪又很正常,UI上,我们只看到了父组件的出现,但没有子组件的内容出现,且也没有父组件的内容被覆盖住,这是因为我们的父组件没有对子组件进行操作,所以就只显示了父组件的内容。
但我们原来的想法是将父组件以及子组件形成一个嵌套,所以就要用到props.children来实现我们想要的效果。需要在父组件中增加对props.children的操作。
function Pcomponent({ children }:any) {
console.log(children);
return (
<div
style={{
border: "1px solid #000",
padding: "10px",
width: "fit-content",
}}
>
父组件
{children}
</div>
);
}
export default Pcomponent;
此时,父组件跟子组件的嵌套就实现了我们的效果.
简单的介绍了Props.children之后,现在开始正题讲解下React.Children.
Children 允许你处理和转化作为 children 的 JSX。
props.children就像是React的插槽一样,将外界的组件直接在我们的父组件中显示出来,但是在上面的例子中,我们直接将其显示出来,并没有做任何操作,尤其是这个是在props上,很少会有人直接动它。
在React的文档中,提供了React.Children这个API 来让我们对组件的children进行操作。但也请记得,React并不建议你使用它来操作组件。
React.Children提供了五个方法来对children进行操作,以便让我们转化Children。
- Children.count(children)
- Children.forEach(children, fn, thisArg?)
- Children.map(children, fn, thisArg?)
- Children.only(children)
- Children.toArray(children)
?接下来用一个最常用的map做例子。
import React from "react";
?
function Pcomponent({ children }: any) {
return (
<div
style={{
border: "1px solid #000",
padding: "10px",
width: "fit-content",
}}
>
父组件
{React.Children.map(children, (child: Element, index: number) => {
return (
<div>
<p>在父组件中给子组件添加了一个p标签</p>
{children[index]}
<hr />
</div>
);
})}
</div>
);
}
export default Pcomponent;
如图,在这儿修改了父组件的代码,给每一个传进来的children组件加入一个?div的外框。而map方法与forEach方法的区别在于?map会返回组件。
为了测试,下面也会修改app.tsx,传入三个组件,其中一个为文本,一个为React的组件,一个为null.
import React from "react";
import Scomponent from "./components/Scomponent";
import "./App.css";
import Pcomponent from "./components/Pcomponent";
?
function App() {
return (
<div className="App">
<Pcomponent>
<Scomponent />
TEST
{null}
</Pcomponent>
</div>
);
}
?
export default App;
在效果图中可以看到,即使是一个null,React.Children也是对其做了操作,将其渲染出来了,即使他是一个null,更不必说?字符串了。
在React的文档中也讲述到了这一点?:
空节点(null,undefined 以及布尔值),字符串,数字和 React 元素 都会被统计为单个节点。在遍历统计的过程中,React
元素不会被渲染,所以其子节点不会被统计。Fragment 也不会被统计。对于数组,它本身也不会被统计,但其中的元素遵循上述规则。
如果你在 fn 中返回了一个具有 key 的元素或者元素数组,各个元素的 key 将自动与其在 children 中对应的原始项的 key
绑定。当你在 fn 中返回了一个包含了多个元素的数组时,其中的每个元素的 key 都需要保证在这个数组中是独一无二的。
此时此刻,我们也只是将页面包裹了起来,添加了一个外框而已,对于我们的Scomponent没有任何的操作也没有任何的办法,我们无法读取到?组件内的内容,更无法对其进行操作(即使可以,也不建议对其操作)。所以如果想要对内部组件的渲染输出结果进行操作的时候,只能在组件中进行自己的逻辑操作了。
请注意,不建议使用Children,毕竟完全可以自己写一个组件对其操作,且新手对Children不熟悉的时候,很容易出现问题。?
呜呜呜,个人公众号,求各位大佬们关注,这是对我的小小鼓励。
公众号主要是写前端的,有Reac以及Express,NodeJs,Angular等