相关文章推荐
谦逊的猴子  ·  typeorm - How do I ...·  1 年前    · 
任性的菠菜  ·  java - Disable Spring ...·  1 年前    · 
class Executioner extends React.Component { render() { // See how we're calling the child as a function? // ↓ return this.props.children(arg) //因为children是函数,所以这里肯定也可以传参 }复制代码

不只如此,children还可以是jsx等等

二、操作children

2.1 React.Children.map

<Executioner>
  {(arg) => <h1>Hello World!</h1>}
</Executioner>
class Executioner extends React.Component {
  render() {
    // See how we're calling the child as a function?
    //                        ↓
    return this.props.children(arg)   //因为children是函数,所以这里肯定也可以传参
}复制代码

像上图我们可以用this.props.children操作,比如我们当我们传了多个子组件之后又要怎么渲染出来呢

如果你看过React官方文档,你会看到说"子组件是一种不透明的数据结构"(opaque data structure)。意思就是props.children可以是任何类型,比如array, function, object等等。因为什么都可以传,所以你也不能确定传过来了什么东西。

<IgnoreFirstChild>
  <h1>First</h1>
  <h1>Second</h1> // <- Only this is rendered
</IgnoreFirstChild>
class IgnoreFirstChild extends React.Component {
  render() {
    const children = this.props.children
    return (
        {this.props.children.map((child, i) => {
          // Ignore the first child
          if (i < 1) return
          return child
        // 这里我们用了this.props.children.map,并且忽略到第一个元素,但是如果这里传进来的是上面
            例子是上图中的函数,这里就会报错,因为map,使用React.Children.map则不会报错
        {React.Children.map(children, (child, i) => {          // Ignore the first child
          if (i < 1) return
          return child
      // 这里我们用了React.Children.map,这是React提供的一些帮助函数
}复制代码

所以使用React.Children.map就没有问题了,这是一种更加稳妥的方式

<IgnoreFirstChild>
  {() => <h1>First</h1>} // <- Ignored 💪
</IgnoreFirstChild>
  //使用this.props.children会报错,用React.Children.map不会报错

2.2 React.Children.count

同样由于this.props.children类型的不确定,我们要判断有多少个子组件就比较困难了。如果幼稚的使用this.props.children.length就很容易报错了。而且,如果传来一个子组件"Hello World!",.length会返回12!

class ChildrenCounter extends React.Component {
  render() {
    return <p>React.Children.count(this.props.children)</p>
}复制代码
// Renders "1"
<ChildrenCounter>
  Second!
</ChildrenCounter>
// Renders "2"
<ChildrenCounter>
  <p>First</p>
  <ChildComponent />
</ChildrenCounter>
// Renders "3"
<ChildrenCounter>
  {() => <h1>First!</h1>}
  Second!
  <p>Third!</p>
</ChildrenCounter>
// 每次都精准算出了子组件的个数复制代码

2.3 React.Children.toArray

当你需要把子组件转化成数组时,可以使用toArray这个函数

class Sort extends React.Component {
  render() {
    const children = React.Children.toArray(this.props.children)
    // Sort and render the children
    return <p>{children.sort().join('')}</p>   
  // We use expression containers to make sure our strings
  // are passed as three children, not as one string
  {'bananas'}{'oranges'}{'apples'}
</Sort>
//输出 apples bananas oranges
  // We use expression containers to make sure our strings
  // are passed as three children, not as one string
</Sort>
//这样子也并不会报错复制代码

2.4 React.Children.only

如果你希望传进来的组件只是一个,而且是个函数

我们先借用proppropTypes来实现

class Executioner extends React.Component {
  render() {
    return this.props.children()
Executioner.propTypes = {
  children: React.PropTypes.func.isRequired,
//这样就会在console里打印出日志来,但是有的时候开发者很容易忽略这些消息。这个时候我们就应该在render方
法里加入React.Children.only。
class Executioner extends React.Component {
  render() {
    return React.Children.only(this.props.children)()
 //如果子组件多于一个会抛出一个错误,整个app会停止--绝对不会让一些偷懒的开发搞乱我们的组件。

2.5 React.cloneElement

比如我们有一个RadioGroup组件,该组件包含一些RadioButton子组件(最终渲染成<input type="radio"> )。

RadioButtons不是由RadioGroup渲染的,它们作为子组件传入,这意味着我们的代码看起来像这样:

render() {
  return(
    <RadioGroup>
      <RadioButton value="first">First</RadioButton>
      <RadioButton value="second">Second</RadioButton>
      <RadioButton value="third">Third</RadioButton>
    </RadioGroup>
}复制代码

但是这样子的话RadioButton不会出现在一个RadioGroup中,所以我们必须给所有的RadioButton加上同一个属性name

<RadioGroup>
  <RadioButton name="g1" value="first">First</RadioButton>
  <RadioButton name="g1" value="second">Second</RadioButton>
  <RadioButton name="g1" value="third">Third</RadioButton>
</RadioGroup>
//这种方法显然可以,但是有点笨复制代码

我们可以先用React.children改写一下

class RadioGroup extends React.Component {
  constructor() {
    super()
    // Bind the method to the component context
    this.renderChildren = this.renderChildren.bind(this)
  renderChildren() {
  return React.Children.map(this.props.children, child => {
    // TODO: Change the name prop to this.props.name
    return child
  render() {
    return (
      <div className="group">
        {this.renderChildren()}
  //这里问题就是我们还是没有给每个RadioButton加上property name

这里我们用上我们最后的一个api React.cloneElement

第一个参数是拷贝源的React element, 第二个参数是prop object,clone以后会把这个prop object设置成属 性给拷贝结果。cloned元素将持有名为new的属性,属性值为"yes!"复制代码

那么这里我们就来改写上面的代码

class RadioGroup extends React.Component {
  constructor() {
    super()
    // Bind the method to the component context
    this.renderChildren = this.renderChildren.bind(this)
  renderChildren() {
    return React.Children.map(this.props.children, child => {
      return React.cloneElement(child,
        name: this.props.name
  render() {
    return (
      <div className="group">
        {this.renderChildren()}
<RadioGroup name="g1">
  <RadioButton value="first">First</RadioButton>
  <RadioButton value="second">Second</RadioButton>
  <RadioButton value="third">Third</RadioButton>
</RadioGroup>
//这样子只需要写个一个name便可以实现功能

 转自React之不简单的Children - 掘金

原文链接:https://juejin.cn/post/6844904036827676686 import React ,{useState}from 'react'; import { PageHeaderWrapper } from '@ant-design/pro-layout'; import styles from './Welcome.less'; import Child from './Child'; export default (): React.ReactNode => { const [msg,s 在项目中,我们可能常常会使用children来接收一个组件的子组件,有的时候,我们或许需要对子组件进行一定的操作.可是如果直接对children进行更改,可能在部分版本中会出现错误,那么我们应该怎么办呢? 我们先了解一下,如何利用children接收子组件 children const Father = (props) => { const { children } = props; return ( <div>我是父组件</div> React.Children 详解 React.Children提供了处理 this.props.children 的 API,this.props.children 支持任何数据(组件、字符串、函数等等)。React.children有5个方法:React.Children.map(),React.Children... ### 因为this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。所以,处理 this.props.children 的时候要小心。 React 提供一个工具方法 React.Children 来处理 this.props.children 。 官网已经不推荐使用ref=字符串的形式, 后来就没用了refs这种形式了, 大多是使用ref=() => {}箭头函数的形式来获取 classParentextendsPureComponent{ componentDidMount(){console.log(this.child._input)//这里就能拿到子组件的input render(... context1. 创建context的两种方式2. createContextConcurrentMode(并发模式syncMode)Supense + lazy(懒加载)React.Children1. React.Children.map 2. React.Children.forEach3. React.Children.count4. React.Children.only5. React.Children.toArraychildContextType(目前已经被弃用了,但是之前被用的很多) 万物始于 jsx,想要深入学习 react ,就应该从 jsx 入手。弄清楚 jsx ,方便学习掌握以下内容: 了解常用的元素会被 React 处理成什么,有利于后续理解 react fiber 类型; 理解 jsx 的编译过程,方便操纵 children、控制 React 渲染,有利于便捷使用 React 插槽组件。...... 在React中,children是一个特殊的prop(属性),代表那些被包含在组件标签之间的组件。它允许你将组件作为数据传递给其他组件,就像你在HTML中嵌套元素一样。这提供了一种强大的方式来创建可复用的组件,这些组件可以封装和管理它们自己的children,无论这些children是静态的、动态的、简单的还是复杂的。