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類變量上。這個變量不屬于某個單獨的對象??衫斫鉃閟tatic 變量
將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閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容