美文网首页ReactreactWeb前端之路
React基础1--生命周期详解

React基础1--生命周期详解

作者: Dabao123 | 来源:发表于2017-08-29 22:50 被阅读147次

    本文解读了react生命周期的源码,如果你还是个入门的小白,当然可以忽略源码,看一看作者写的demo。也可以明白生命周期奥义。

    React基础1--生命周期详解

    React组件生命周期根据广义的定义,可分为挂在、渲染和卸载几个阶段。当渲染后的组件再次更新时,react会重新去渲染组件,直至卸载。
    在定义组建的时候,我们会根据需要在组件在生命周期不同阶段实现不同逻辑。

    当组件首次挂载时,按顺序执行getDefaultProps、getInitialState、componentWillMount、render、componentDidMount。

    当卸载组件时,执行componentWillUnmount

    当重新挂载组件时候,此时按顺序执行 getInitialState、componentWillMount、 render、componentDidMount(此时不会执行getDefaultProps)

    当组件重新渲染时,组件接收到更新状态,此时执行顺序是:componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate
    在es6的与法理static defaultProps = {} 相当于其实就是调用内部的getDefaultProps,this.state = {} 就相当于getInitialState。
    自定义组件的生命周期主要通过三个阶段:
    MOUNTING、RECEIVE_PROPS、UNMOUNTING对应的方法分别为:mountComponent、updateComponent、unmountComponent

    一、使用createClass创建自定义组件

    createClass方法是创建自定义组件的入口方法。该方法只在生命周期中调用一次,所有的实例化的props都会共享。

    Paste_Image.png

    找到ReactClass.js

    Paste_Image.png

    以下为源码

    var ReactClass = {
      createClass: function (spec) {
        var Constructor = function (props, context, updater) {
          // 触发自动绑定
          if (this.__reactAutoBindPairs.length) {
            bindAutoBindMethods(this);
          }
          // 初始化参数
          this.props = props;
          this.context = context;
          this.refs = emptyObject;// 本组件对象的引用,可以利用它来调用组件的方法
          this.updater = updater || ReactNoopUpdateQueue;
           // 调用getInitialState()来初始化state变量
          this.state = null;
    
          var initialState = this.getInitialState ? this.getInitialState() : null;
          if (initialState === undefined && this.getInitialState._isMockFunction) {
              initialState = null;
          }
          this.state = initialState;
        };
      // 继承父类
        Constructor.prototype = new ReactClassComponent();
        Constructor.prototype.constructor = Constructor;
        Constructor.prototype.__reactAutoBindPairs = [];
       //按顺序合并mixins
        injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));
        mixSpecIntoComponent(Constructor, spec);
       // 待到所有mixins合并完成,调用getDefaultProps,并挂载到组件类上(整个周期只会调用一次)。
        if (Constructor.getDefaultProps) {
          Constructor.defaultProps = Constructor.getDefaultProps();
        }
       if (Constructor.getDefaultProps) {
            Constructor.getDefaultProps.isReactClassApproved = {};
       }
       if (Constructor.prototype.getInitialState) {
           Constructor.prototype.getInitialState.isReactClassApproved = {};
       }
        !Constructor.prototype.render ? process.env.NODE_ENV !== 'production' ? invariant(false, 'createClass(...): Class specification must implement a `render` method.') : _prodInvariant('83') : void 0;
        // 减少查找,并设置原型时间
        // React中暴露给应用调用的方法,如render componentWillMount。
        // 如果应用未设置,则将他们设为null
        for (var methodName in ReactClassInterface) {
          if (!Constructor.prototype[methodName]) {
            Constructor.prototype[methodName] = null;
          }
        }
    
        return Constructor;
      },
    
      injection: {
        injectMixin: function (mixin) {
          injectedMixins.push(mixin);
        }
      }
    
    };
    

    createClass主要做了:
    定义构造方法Constructor,构造方法中进行props,refs等的初始化,并调用getInitialState来初始化state
    调用getDefaultProps,并放在defaultProps类变量上。这个变量不属于某个单独的对象。可理解为static 变量
    将React中暴露给应用,但应用中没有设置的方法,设置为null。

    二、MOUNTING

    MOUNTING阶段定义的方法是mountCompont,如ReactCompositeComponent.js下



    所示

    //初始化组件,注册事件监听
    mountComponent: function (transaction, hostParent, hostContainerInfo, context) {
        //当前元素对应的上下文
        this._context = context;
        this._mountOrder = nextMountID++;
        this._hostParent = hostParent;
        this._hostContainerInfo = hostContainerInfo;
        // 添加到ReactComponentElement元素的props属性  
        var publicProps = this._currentElement.props;
        // 通过Component.contextTypes过滤由上层组件注入的context属性,并做校验
        var publicContext = this._processContext(context);
        // 纯函数无状态组件、或者继承自PureComponent的纯组件构造函数、或者继承自Component的组件构造函数  
        var Component = this._currentElement.type;
        // 传入组件ReactComponent的第三个参数updater,默认是ReactUpdateQueue模块,用于实现setState等方法  
        var updateQueue = transaction.getUpdateQueue();
        // 校验是否纯组件或组件;返回否值,当作非状态组件、或ReactClass的工厂函数处理
        var doConstruct = shouldConstruct(Component);
        // 创建纯组件或组件实例,或者获取无状态组件的返回值 
        var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);
        // 待挂载的ReactComponentElement元素
        var renderedElement;
       // 无状态组件,没有更新队列它只专注于渲染
        if (!doConstruct && (inst == null || inst.render == null)) {
          renderedElement = inst;
          warnIfInvalidElement(Component, renderedElement);
          // 将无状态组件function(props,context,updateQueue){}包装为带有render原型方法的构造函数形式  
          inst = new StatelessComponent(Component);
          this._compositeType = CompositeTypes.StatelessFunctional;
        } else {
          if (isPureComponent(Component)) {
             // 添加纯组件标识 
            this._compositeType = CompositeTypes.PureClass;
          } else {
            // 添加组件标识  
            this._compositeType = CompositeTypes.ImpureClass;
          }
        }
        // 原本作为构造函数的参数传入,为方便起见,再次赋值,同时保证实例数据的准确性
        inst.props = publicProps;
        inst.context = publicContext;
        inst.refs = emptyObject;
        inst.updater = updateQueue;
        
        // ReactInstanceMap中添加组件实例  
        this._instance = inst;
        ReactInstanceMap.set(inst, this);
    
        // 获取初始state,并提示state只能设置为对象形式
        var initialState = inst.state;
        if (initialState === undefined) {
          inst.state = initialState = null;
        }
      
        this._pendingStateQueue = null;
        this._pendingReplaceState = false;
        this._pendingForceUpdate = false;
        // 执行实例inst的render方法,嵌套调用mountComponent,将返回值ReactNode元素转化成DomLazyTree输出  
        var markup;
        if (inst.unstable_handleError) {
          markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);
        } else {
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
        }
        // 向后置钩子transaction.getReactMountReady()中添加实例的生命周期方法componentDidMount
        if (inst.componentDidMount) {
          if (process.env.NODE_ENV !== 'production') {
            transaction.getReactMountReady().enqueue(invokeComponentDidMountWithTimer, this);
          } else {
            transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
          }
        }
        return markup;
      }
    
     performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
        var markup;
        var checkpoint = transaction.checkpoint();
        try {
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
        } catch (e) {
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onError();
            }
          }
     
          transaction.rollback(checkpoint);
          this._instance.unstable_handleError(e);
          if (this._pendingStateQueue) {
            // _processPendingState方法获取组件setState、replaceState方法执行后的最终state
            this._instance.state = this._processPendingState(this._instance.props, this._instance.context);
          }
          checkpoint = transaction.checkpoint();
    
          this._renderedComponent.unmountComponent(true);
          transaction.rollback(checkpoint);
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);
        }
        return markup;
      },
    
    performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {
        var inst = this._instance;
         // 执行组件实例的componentWillMount方法  
         // componentWillMount方法内调用setState、replaceState,_pendingStateQueue有值,刷新state后再行绘制  
          inst.componentWillMount();
          if (this._pendingStateQueue) {
              // _processPendingState方法获取组件setState、replaceState方法执行后的最终stat
            inst.state = this._processPendingState(inst.props, inst.context);
          }
        }
        // 间接执行ReactClass或TopLevelWrapper实例的render方法,获取待挂载的元素ReactNode  
        // 组件若为函数式无状态组件function(props,context,updateQueue){},renderedElement由传参提供  
        if (renderedElement === undefined) {
           // 调用组件实例inst的render方法,获取待挂载的元素ReactNode  
          renderedElement = this._renderValidatedComponent();
        }
    
        var nodeType = ReactNodeTypes.getType(renderedElement);
        this._renderedNodeType = nodeType;
        var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */
        );
        // render方法内子组件实例 
        this._renderedComponent = child;
        var selfDebugID = 0;
        // 嵌套调用mountComponent,完成renderedElement元素相应组件的实例化及render方法执行  
        // 最终通过ReactDomElement转化为DOMLazyTree对象输出,其node属性为需要插入文档dom对象 
     var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), selfDebugID);
    
    
        return markup;
      }
    

    在组件挂载的过程中,propTypes和defaultProps分别代表props类型检查和默认类型。之后我们会看到两个方法componentWillMount和componentDidMount,其中,componentWillMount在render之前执行,componentDidMount在render之后执行分别代表了渲染前后的时刻。如果我们在componentWillMount执行setState方法,组件会更新state,但是组件只渲染一次。因此这是无意义的,初始化state可以放在this.state里。
    其实,mountComponent本质上是通过递归渲染内容的,父组件的componentWillMount在子组件的componentWillMount之前调用,componentDidMount在子组件的componentDidMount之后调用。
    看下面一组代码:

    class Botton extends React.Component{
        constructor(props){
            super(props)
            this.state = {
                value:false,
                pro : 'aaa'
            }
        }
        componentWillMount(){
          console.log('子组件willmount')
        }
        componentDidMount(){
             console.log('子组件didmount')
             this.setState({pro:'bbb'})
          }
        setSta(){
           this.setState({
            value: true,
          })
        }
        set(){
            this.setState({
                pro: '1111',
            })
        }
        render(){
          console.log("子组件render")
          let comp ,style;
          const { value } = this.state;
          return(
            <div>
            <button onClick={ this.setSta.bind(this) }>切换</button>
            <button onClick={ this.set.bind(this) }>切换2</button>
            </div>
          )
       }
    }
    
    class Wrap extends React.Component {
        constructor(props){
            super(props)
            this.state = {
                value : false
            }
        }
        componentWillMount(){
          console.log('父组件willmount')
        }
        componentDidMount(){
           console.log('父组件didmount')
        }
        sets(){
            this.setState({
                value : true
            })
        }
        render(){
        console.log("父组件render")
            let style;
            if(this.state.value){
                style = {
                    display : 'block'
                }
            }else{
                style = {
                    display : 'none'
                }
            }
            return(
                <div>
                    <Botton style={style}/>
                    <button onClick={this.sets.bind(this)}>切换</button>
                </div>
            )
        }
    }
    const handleChange = (value) => {
      console.log(value)
    }
    ReactDOM.render(
      <div>
          <Wrap />
      </div>,
      document.getElementById('app')
    )
    

    运行结果:

    Paste_Image.png

    首先父组件wrap 初始化 props state,之后执行wrap的componentWillMount方法,合并state,执行render方法,在render方法里调用Botton组件,之后执行Botton的componentWillMount -- render --componentDidMount 然后执行父组件componentDidMount。

    三、RECEIVE_PROPS阶段

    还是先看源码:

    // 接受新的组件待渲染元素nextElement,以替换旧的组件元素this._currentElement  
    // 通过performUpdateIfNecessary方法调用,nextElement由this._pendingElement提供  
    // 该方法触发执行的实际情形是ReactDom.render(ReactNode,pNode)挂载的组件元素,其父节点pNode由react方式绘制  
    // 通过_updateRenderedComponent方法调用,nextElement为待变更的子组件元素  
    receiveComponent: function (nextElement, transaction, nextContext) {
        var prevElement = this._currentElement;
        var prevContext = this._context;
        this._pendingElement = null;
        this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);
      },
    
    // 判断props变更情况,执行shouldComponentUpdate方法,重绘组件或者更改组件的属性  
    // 参数transaction,组件重绘时用于向子组件提供updater参数,setState等方法可用;以及实现componentWillMount挂载功能  
    // 参数prevParentElement变更前的组件元素ReactNode,nextParentElement变更后的组件元素,作为render方法渲染节点的父元素  
    // 参数prevUnmaskedContext更迭前的context,nextUnmaskedContext更迭后的context  
    updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {
        var inst = this._instance;
        var willReceive = false;
        var nextContext;
    
        // 更新context  
        if (this._context === nextUnmaskedContext) {
          nextContext = inst.context;
        } else {
          nextContext = this._processContext(nextUnmaskedContext);
          willReceive = true;
        }
    
        var prevProps = prevParentElement.props;
        var nextProps = nextParentElement.props;
    
        // 包含仅待渲染元素的props变更 
        if (prevParentElement !== nextParentElement) {
          willReceive = true;
        }
    
        // 更新context、或变更带渲染组件元素或其props时willReceive赋值为真,由父组件发起,调用componentWillReceiveProps方法 
        if (willReceive && inst.componentWillReceiveProps) {
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
            }
          }
          inst.componentWillReceiveProps(nextProps, nextContext);
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillReceiveProps');
            }
          }
        }
       //将最新的state合并到队列中
        var nextState = this._processPendingState(nextProps, nextContext);
       //更新组件 
       var shouldUpdate = true;
        // 调用组件的shouldComponentUpdate判断是否需要重绘  
        // 纯组件不能设置shouldComponentUpdate方法,仅判断props、state是否变更
        if (!this._pendingForceUpdate) {
          if (inst.shouldComponentUpdate) {
            if (process.env.NODE_ENV !== 'production') {
              if (this._debugID !== 0) {
                ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
              }
            }
            shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);
            if (process.env.NODE_ENV !== 'production') {
              if (this._debugID !== 0) {
                ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'shouldComponentUpdate');
              }
            }
          } else {
            if (this._compositeType === CompositeTypes.PureClass) {
              shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);
            }
          }
        }
        this._updateBatchNumber = null;
        if (shouldUpdate) {
           //重新更新队列
          this._pendingForceUpdate = false;
          // 执行componentWillUpdate方法,重绘组件实例render方法内待渲染的子组件,挂载componentDidUpdate方法
          this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);
        } else {
          // 只变更组件的部分属性,不开启重绘功能  
          this._currentElement = nextParentElement;
          this._context = nextUnmaskedContext;
          inst.props = nextProps;
          inst.state = nextState;
          inst.context = nextContext;
        }
      },
    
     // 执行componentWillUpdate方法,重绘组件实例render方法内待渲染的子组件,挂载componentDidUpdate方法
     _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {
        var inst = this._instance;
        var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);
        var prevProps;
        var prevState;
        var prevContext;
        // 如果存在componentDidUpdate就将props、state、context保存一份
        if (hasComponentDidUpdate) {
          prevProps = inst.props;
          prevState = inst.state;
          prevContext = inst.context;
        }
        // 执行componentWillUpdate方法 
        if (inst.componentWillUpdate) {
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onBeginLifeCycleTimer(this._debugID, 'componentWillUpdate');
            }
          }
          inst.componentWillUpdate(nextProps, nextState, nextContext);
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onEndLifeCycleTimer(this._debugID, 'componentWillUpdate');
            }
          }
        }
        this._currentElement = nextElement;
        this._context = unmaskedContext;
       //更新props、state、context
        inst.props = nextProps;
        inst.state = nextState;
        inst.context = nextContext;
        // 以更新子组件的方式或重新创建子组件的方式重绘render方法待渲染的子组件
        this._updateRenderedComponent(transaction, unmaskedContext);
       // 向后置钩子transaction.getReactMountReady()中添加实例的生命周期方法componentDidUpdate
        if (hasComponentDidUpdate) {
          if (process.env.NODE_ENV !== 'production') {
            transaction.getReactMountReady().enqueue(invokeComponentDidUpdateWithTimer.bind(this, prevProps, prevState, prevContext), this);
          } else {
            transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);
          }
        }
      },
    
    // 以更新子组件的方式或重新创建子组件的方式重绘render方法待渲染的子组件
     _updateRenderedComponent: function (transaction, context) {
        // 组件render待渲染的子组件实例
        var prevComponentInstance = this._renderedComponent;
        var prevRenderedElement = prevComponentInstance._currentElement;
        // _renderValidatedComponent方法调用组件实例inst的render方法,获取待挂载的元素
        var nextRenderedElement = this._renderValidatedComponent();
    
        // shouldUpdateReactComponent方法返回真值,更新组件实例;返回否值,销毁实例后、重新创建实例  
        // 组件元素的构造函数或key值不同,销毁实例后再行创建   
        // render方法子组件构造函数及key相同,通过ReactReconciler.receiveComponent方法更新子组件实例  
        if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {
          ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));
        } else {
           //渲染组件
          var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);
          ReactReconciler.unmountComponent(prevComponentInstance, false);
    
          var nodeType = ReactNodeTypes.getType(nextRenderedElement);
          this._renderedNodeType = nodeType;
          var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), selfDebugID);
    
          if (process.env.NODE_ENV !== 'production') {
            if (this._debugID !== 0) {
              ReactInstrumentation.debugTool.onSetChildren(this._debugID, child._debugID !== 0 ? [child._debugID] : []);
            }
          }
          // 替换文档中挂载的Dom元素DomLazyTree  
          this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);
        }
      },
    

    updateComponent方法:负责判断props变更情况,调用componentWillReceiveProps方法,无论属性是否变化,只要父组件发生render的时候子组件就会调用componentWillReceiveProps。调用组件的shouldComponentUpdate判断是否需要更新。
    _performComponentUpdate方法:负责执行componentWillUpdate方法,重绘组件实例render方法内待渲染的子组件,挂载componentDidUpdate方法。
    _updateRenderedComponent方法:更新子组件的方式或重新创建子组件的方式重绘render方法待渲染的子组件

    upadteComponent负责管理生命周期的componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate。
    通过下面例子具体看一下:

    class Botton extends React.Component{
        constructor(props){
            super(props)
            this.state = {
                value:false,
                pro : 'aaa'
            }
        }
        componentWillMount(){
          console.log('子组件willmount')
        }
        componentDidMount(){
             console.log('子组件didmount')
             this.setState({pro:'bbb'})
          }
        componentWillUpdate(){
          console.log('子组件WillUpdata')
        }
        componentDidUpdate(){
           console.log('子组件DidUpdata')
        }
        componentWillReceiveProps(nextProps) {
            console.log('子组件WillReceiveProps')
        }
        setSta(){
           this.setState({
            value: true,
          })
        }
        set(){
            this.setState({
                pro: '1111',
            })
        }
        render(){
          console.log("子组件render")
          let comp ,style;
          const { value } = this.state;
          if(value){
                comp = (
                <div >
                    你好
                    <p>123</p>
                </div>
            )
          }else{
            comp = (
                <div >
                    ta好
                </div>
            )
          }  
          return(
            <div>
            {comp}
            <button onClick={ this.setSta.bind(this) }>切换</button>
            <button onClick={ this.set.bind(this) }>切换2</button>
            </div>
          )
       }
    }
    
    class Wrap extends React.Component {
        constructor(props){
            super(props)
            this.state = {
                value : false
            }
        }
        componentWillMount(){
          console.log('父组件willmount')
        }
        componentDidMount(){
           console.log('父组件didmount')
           this.setState({pro:'bbb'})
        }
        componentWillUpdate(){
          console.log('父组件WillUpdata')
        }
        componentDidUpdate(){
           console.log('父组件DidUpdata')
        }
        sets(){
            this.setState({
                value : true
            })
        }
        render(){
        console.log("父组件render")
            let style;
            if(this.state.value){
                style = {
                    display : 'block'
                }
            }else{
                style = {
                    display : 'none'
                }
            }
            return(
                <div>
                    <Botton style={style }/>
                    <button onClick={this.sets.bind(this)}>切换</button>
                </div>
            )
        }
    }
    ReactDOM.render(
      <div>
          <Wrap />
      </div>,
      document.getElementById('app')
    )
    

    运行结果:

    Paste_Image.png

    当我们点击父级切换按钮的时候调用sets方法,从而执行setState方法,于是父级组件开始进入RECEIVE_PROPS阶段。

    Paste_Image.png

    从执行结果上看更新过程也是递归执行的。
    shouldComponentUpdate:
    组件挂载之后,每次调用setState后都会调用shouldComponentUpdate判断是否需要重新渲染组件。默认返回true,需要重新render。在比较复杂的应用里,有一些数据的改变并不影响界面展示,可以在这里做判断,优化渲染效率。

    //在botton里添加
     shouldComponentUpdate(){
          return false;
        }
    

    结果

    Paste_Image.png
    四、UNMOUNTING

    生命周期的最后一个阶段componentWillUnmount代表将要卸载。
    在componentWillUnmount内所有的状态都被置为null

    if (this._renderedComponent) {
          ReactReconciler.unmountComponent(this._renderedComponent, safely);
          this._renderedNodeType = null;
          this._renderedComponent = null;
          this._instance = null;
        }
        this._pendingStateQueue = null;
        this._pendingReplaceState = false;
        this._pendingForceUpdate = false;
        this._pendingCallbacks = null;
        this._pendingElement = null;
        this._context = null;
        this._rootNodeID = 0;
        this._topLevelWrapper = null;
        //清除公公类
        ReactInstanceMap.remove(inst);
    

    看完生命周期,我想大家应该对props、state有了新的认识。大家可以深入去读一些源码,了解react的生命周期,在编程上会给大家更多的帮助。
    我们试着分析一下上面的那个demo:
    1.最外层组件wrap我们并没有设置props所以它的props是空的,
    2.this.state即getInitialState 设置了一个value = false
    3.执行自己的componentWillMount方法
    4.合并state
    5.执行render方法,

    <Botton style={{display:'none'}}/>
    

    我们在此给 Botton设置了 style 属性
    6.执行getDefaultProps方法设置style属性
    7.执行getInitialState方法即this.state = {
    value:false,
    pro : 'aaa'
    }
    8.执行componentWillMount方法
    9.合并state
    10.执行render方法
    11.执行componentDidMount方法
    12.执行父级Wrap的componentDidMount方法,此时我们设置
    setState({
    value : true
    })
    13.Wrap会执行componentWillUpdate方法(shouldComponentUpdate默认为更新)
    14.创建component实例
    15.render
    16.子组件调用componentWillReceiveProps
    17.shouldComponentUpdate默认为更新
    18.调用componentWillUpdate
    19.创建component实例 render
    20.componentDidUpdate
    21.Wrap组件componentDidUpdate
    当点击 切换按钮时
    继续13-21.
    有错欢迎指正。
    下一篇我们深入挖掘 setState 函数。
    你也可以看其他文章
    React基础2--深入挖掘setState
    React基础3--diff算法

    相关文章

      网友评论

        本文标题:React基础1--生命周期详解

        本文链接:https://www.haomeiwen.com/subject/hcgbdxtx.html