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

本文解读了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算法

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容