关于javascript:react的父子组件执行顺序

12次阅读

共计 3938 个字符,预计需要花费 10 分钟才能阅读完成。

执行程序

1. 父类的 ComponentWillMount
2. 父类的 render
3. 子类 1 的 ComponentWillMount
4. 子类 1 的 render
5. 子类 2 的 ComponentWillMount
6. 子类 2 的 render
7. 子类 1 的 ComponentDidMount
8. 子类 2 的 ComponentDidMount
9. 父类的 ComponentDidMount

组件挂载的过程:

初始化 props,通过类的动态属性 defaultProps 或者 getDefaultProps 函数,初始化的 props 会与父组件指定的 props 合并,最初赋值给 this.props
constructor(),或者 getInitialState
componentWillMount(),此时 dom 还没渲染,在这里执行的 setState 不会导致重绘,执行无成果
render()
componentDidMount(),在这里执行的 setState 会导致重绘(或称为二次渲染)
被动更新流程(父组件调用 setState)

componentWillReceiveProps(),这时子组件的 props 依然是旧的,能够在这里把新的 props 通过 setState 设置进 state 中,不会触发二次渲染
shouldComponentUpdate(),这里读取到的 state 是以上更新后的 state
componentWillUpdate(),不能在这里执行 setState,执行了无成果
render()
componentDidUpdate(),能够在这里进行异步的 setState
被动更新流程(以后组件调用 setState)

执行的函数相比下面的被动更新流程,少了一个 componentWillReceiveProps 办法,其余的都一样。
卸载

componentWillUnmount(),用于革除定时器、事件绑定;React 官网不倡议在 componentWillMount() 批改 state,通常倡议在 componentDidMount(), 如果须要设置 state 的初始状态,能够在 (es6:)constructor() 或者 (es5:)getInitialState() 中设置。

setState 是一个异步操作,批改的 state 必能通过 this.state.xxx 来马上读取,但能够在 setState 的第二个参数(回调函数)中读取更新后的值。执行这个函数的时候,新状态会被寄存进队列中,稍后才进行状态合并,接着触发 shouldComponentUpdate 和 render,所以间断屡次的 setState 不会影响效率,只会触发一次 render

import React from 'react';
import ReactDOM from 'react-dom';
const buildClass = (name)=>{
    return class extends React.Component{constructor(props) {super(props);
            console.log(name + 'constructor');
        }
        componentWillMount() {console.log( name + 'componentWillMount');
        }
        componentDidMount() {console.log( name + 'componentDidMount');
        }
        componentWillUnmount() {console.log( name + 'componentWillUnmount');
        }
        componentWillReceiveProps(nextProps) {console.log( name + 'componentWillReceiveProps(nextProps)');
        }
        shouldComponentUpdate(nextProps, nextState) {console.log( name + 'shouldComponentUpdate(nextProps, nextState)');
            return true;
        }
        componentWillUpdate(nextProps, nextState) {console.log( name + 'componentWillUpdate(nextProps, nextState)');
        }
        componentDidUpdate(prevProps, prevState) {console.log( name + 'componetDidUpdate(prevProps, prevState)');
        }
    }
}
class Child extends buildClass('Child'){render(){console.log('Child render')
        return (<div>child</div>)
    }
}
class Parent extends buildClass('Parent'){render(){console.log('Parent render')
        return (<Child />)
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById('root')
}

执行后果

Parent constructor
Parent componentWillMount
Parent render
Child constructor
Child componentWillMount
Child render
Child componentDidMount
Parent componentDidMount

总结:当执行 render 子组件的时候,才会进入子组件的生命周期,子组件的周期完结后,再回到下级的周期。

更新组件的两种形式

1. 被动更新:组件通过 setState 批改本人的状态。
批改子组件的代码:


class Child extends buildClass('Child'){render(){console.log('Child render')
        return (<button onClick={()=>{this.setState({data:123})}}>child</button>
        )
    }
}

执行后果


Child shouldComponentUpdate(nextProps, nextState)
Child componentWillUpdate(nextProps, nextState)
Child render
Child componetDidUpdate(prevProps, prevState)

2. 被动更新:父组件通过 props 把本人的 state 传递给子组件,父组件执行 setState 更新状态
还原子组件的代码,批改父组件代码如下:

class Parent extends buildClass('Parent'){render(){console.log('Parent render')
        return (
            <div>
                <Child />
                <button onClick={()=>{this.setState({data:123})}}>Parent</button>
            </div>
        )
    }

执行后果

Parent shouldComponentUpdate(nextProps, nextState)
Parent componentWillUpdate(nextProps, nextState)
Parent render
Child componentWillReceiveProps(nextProps)
Child shouldComponentUpdate(nextProps, nextState)
Child componentWillUpdate(nextProps, nextState)
Child render
Child componetDidUpdate(prevProps, prevState)
Parent componetDidUpdate(prevProps, prevState)

总结:不论父组件有没有把数据传递给子组件,只有父组件 setState,都会走一遍子组件的更新周期。而且子组件被动更新会比被动更新所执行的流程多进去一个
componentWillReceiveProps 办法。

如果在以上被动更新的根底上,批改 buildClass 中的代码,使 shouldComponentUpdate 返回 false,代码如下:

shouldComponentUpdate(nextProps, nextState) {console.log( name + 'shouldComponentUpdate(nextProps, nextState)');
    return false;
}

点击 parent 中的更新按钮,仅仅输入一句:
Parent shouldComponentUpdate(nextProps, nextState)

论断:只有组件在以上函数中返回 false,则子组件不会进行更新 re-render,所有更新流程都不执行了。

我的解决方案

父类 ComponentDidMount 发申请
render 中判断数据是否拿到
拿到之后再挂载子类组件
并且为了保障如果以后组件被封成一个 Component 之后其他人可能失常应用
因而依据无状态组件的特点
在以后组件的外层封装无状态组件(用来依据数据是否获取确定组件的加载机会)
这时候间接在父类中引入这个无状态组件
保障父类不会晓得这个组件被提早加载

其余解决方案

父组件依然在 componentDidMount 外面发送申请
子组件在 componentWillReceiveProps 中判断数据是否存在
存在的话就在子类的 componentWillReceiveProps 中发送申请

正文完
 0