父子组件按啥顺序呈现?

Posted

技术标签:

【中文标题】父子组件按啥顺序呈现?【英文标题】:In which order are parent-child components rendered?父子组件按什么顺序呈现? 【发布时间】:2017-11-23 02:40:16 【问题描述】:

如果我有两个这样的组件(父母和孩子):

1-父母(倒计时):

var Countdown = React.createClass(
  getInitialState: function()
    returncount: 0;
  ,
  handleSetCountdown: function(seconds)
    this.setState(
      count: seconds
    );
  ,
  render:function()
    var count = this.state;
    return(
      <div>
        <Clock totalSeconds=count/>
        <CountdownForm onSetCountdown=this.handleSetCountdown />
      </div>
    );
  
);

module.exports =Countdown;

2-The Child (CountdownForm):

var CountdownForm = React.createClass(
  onSubmit: function(e)
    e.preventDefault();
    var strSeconds = this.refs.seconds.value;
    if(strSeconds.match(/^[0-9]*$/))
      this.refs.seconds.value ='';
      this.props.onSetCountdown(parseInt(strSeconds,10));

    
  ,
  render: function()
    return(
      <div>
        <form ref="form" onSubmit=this.onSubmit className="countdown-form">
          <input type="text" ref="seconds" placeholder="Enter Time In Seconds"/>
          <button className="button expanded">Start</button>
        </form>
      </div>
    );
  
);

module.exports = CountdownForm;

我对生命周期(渲染组件的顺序)感到困惑?

【问题讨论】:

【参考方案1】:

我没有立即在 React 文档中看到明确的“这是父子之间的生命周期事件的顺序”,尽管我可能会错过它。

当然,凭经验确定是微不足道的:

class Child extends React.Component 
    constructor(...args) 
        super(...args);
        console.log("Child constructor");
    
    componentWillMount(...args) 
        console.log("Child componentWillMount");
    
    componentDidMount(...args) 
        console.log("Child componentDidMount");
    
    render() 
        console.log("Child render");
        return <div>Hi there</div>;
    


class Parent extends React.Component 
    constructor(...args) 
        super(...args);
        console.log("Parent constructor");
    
    componentWillMount(...args) 
        console.log("Parent componentWillMount");
    
    componentDidMount(...args) 
        console.log("Parent componentDidMount");
    
    render() 
        console.log("Parent render start");
        const c = <Child />;
        console.log("Parent render end");
        return c;
    


ReactDOM.render(<Parent />, document.getElementById("react"));
.as-console-wrapper 
  max-height: 100% !important;
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

这显示了我们的顺序:

父构造函数 父组件WillMount 父渲染开始 父渲染结束 子构造函数 子组件WillMount 子渲染 子组件DidMount 父组件DidMount

这让我想知道父母中孩子的顺序,所以:

class Child extends React.Component 
    constructor(props, ...rest) 
        super(props, ...rest);
        console.log(this.props.name + " constructor");
    
    componentWillMount(...args) 
        console.log(this.props.name + " componentWillMount");
    
    componentDidMount(...args) 
        console.log(this.props.name + " componentDidMount");
    
    render() 
        console.log(this.props.name + " render");
        return <div>Hi from this.props.name!</div>;
    


class Parent extends React.Component 
    constructor(...args) 
        super(...args);
        console.log("Parent constructor");
    
    componentWillMount(...args) 
        console.log("Parent componentWillMount");
    
    componentDidMount(...args) 
        console.log("Parent componentDidMount");
    
    render() 
        console.log("Parent render start");
        const result =
            <div>
                <Child name="Child1" />
                <Child name="Child2" />
            </div>;
        console.log("Parent render end");
        return result;
    


ReactDOM.render(<Parent />, document.getElementById("react"));
.as-console-wrapper 
  max-height: 100% !important;
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

这给了我们:

父构造函数 父组件WillMount 父渲染开始 父渲染结束 Child1 构造函数 Child1 组件WillMount Child1 渲染 Child2 构造函数 Child2 组件WillMount Child2 渲染 Child1 组件DidMount Child2 组件DidMount 父组件DidMount

一点也不奇怪,但最好仔细检查一下。 :-)

【讨论】:

【参考方案2】:

只需将componentWillUnmount添加到循环中:

class Child extends React.Component 
    constructor(props, ...rest) 
        super(props, ...rest);
        console.log(this.props.name + " constructor");
    
    componentWillMount(...args) 
        console.log(this.props.name + " componentWillMount");
    
    componentWillUnmount(...args) 
        console.log(this.props.name + " componentWillUnmount");
    
    componentDidMount(...args) 
        console.log(this.props.name + " componentDidMount");
    
    render() 
        console.log(this.props.name + " render");
        return <div>Hi from this.props.name!</div>;
    


class Parent extends React.Component 
    constructor(...args) 
        super(...args);
        console.log("Parent constructor");
    
    componentWillMount(...args) 
        console.log("Parent componentWillMount");
    
    componentWillUnmount(...args) 
        console.log("Parent componentWillUnmount");
    
    componentDidMount(...args) 
        console.log("Parent componentDidMount");
    
    render() 
        console.log("Parent render start");
        const result =
            <div>
                <Child name="Child1" />
                <Child name="Child2" />
            </div>;
        console.log("Parent render end");
        return result;
    


class ParentWrapper extends React.Component 
    constructor(...args) 
        super(...args);
        this.state =  showParent: true ;
        setTimeout(() =>  this.setState( showParent: false ) );
    
    render() 
        return <div>this.state.showParent ? <Parent /> : ''</div>;
    


ReactDOM.render(<ParentWrapper />, document.getElementById("react"));
.as-console-wrapper 
  max-height: 100% !important;
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

结果:

Parent constructor
Parent componentWillMount
Parent render start
Parent render end
Child1 constructor
Child1 componentWillMount
Child1 render
Child2 constructor
Child2 componentWillMount
Child2 render
Child1 componentDidMount
Child2 componentDidMount
Parent componentDidMount
Parent componentWillUnmount
Child1 componentWillUnmount
Child2 componentWillUnmount

【讨论】:

【参考方案3】:

现场演示

react-parent-child-lifecycle-order

https://33qrr.csb.app/

https://codesandbox.io/s/react-parent-child-lifecycle-order-33qrr

创建订单


parent constructor
parent WillMount
parent render

child constructor
child WillMount
child render
child DidMount

parent DidMount

破坏秩序

parent WillUnmount

child WillUnmount

// child unmount

// parent unmount



【讨论】:

【参考方案4】:

render order是按照react组件树的顺序执行的,但是mount order是相反的(最里面的子组件挂载首先。)

【讨论】:

【参考方案5】:

可以使父级的 ComponentDidMount 方法在子级的 ComponentDidMount 方法之前执行。 下面是它的完成方式。

在父级的第一个 div 中,在渲染任何内容之前,检查状态是否已设置。仅在设置状态时才渲染任何内容。

例子:

render() 
  const  t  = this.props;
  return (
    <div>
      this.state.row !== null ? (
            ...
      ) : null
    </div>
  );

【讨论】:

以上是关于父子组件按啥顺序呈现?的主要内容,如果未能解决你的问题,请参考以下文章

vue父子组件加载顺序

react 父子组件执行顺序

Vue父子组件生命周期执行顺序

vue 父子组件生命周期函数执行顺序

Vue中父子组件生命周期的执行顺序

react的父子组件执行顺序