React生命周期執行順序詳解


文章內容轉載於https://www.cnblogs.com/faith3/p/9216165.html

一、組件生命周期的執行次數是什么樣子的???

只執行一次: constructor、componentWillMount、componentDidMount

執行多次:render 、子組件的componentWillReceiveProps、componentWillUpdate、componentDidUpdate

有條件的執行:componentWillUnmount(頁面離開,組件銷毀時)

不執行的:根組件(ReactDOM.render在DOM上的組件)的componentWillReceiveProps(因為壓根沒有父組件給傳遞props)

二、組件的生命周期執行順序是什么樣子的???

  假設組件嵌套關系是 App里有parent組件,parent組件有child組件。

如果不涉及到setState更新,第一次渲染的順序如下:

App:   constructor --> componentWillMount -->  render --> 
parent: constructor --> componentWillMount -->  render --> 
child:    constructor --> componentWillMount -->  render  --> 
componentDidMount (child) -->  componentDidMount (parent) --> componentDidMount (App)

這時候觸發App的setState事件

App:   componentWillUpdate --> render --> 
parent: componentWillReceiveProps --> componentWillUpdate --> render --> 
child:    componentWillReceiveProps --> componentWillUpdate --> render -->
componentDidUpdate (child) -->  componentDidUpdate (parent) --> componentDidUpdate (App)

那如果是觸發parent的setState呢?

parent: componentWillUpdate --> render --> 
child:     componentWillReceiveProps --> componentWillUpdate --> render --> 
componentDidUpdate (child) -->  componentDidUpdate (parent) 

那如果是只是觸發了child組件自身的setState呢?

child: componentWillUpdate --> render -->  componentDidUpdate (child)
結論:
  1. 如圖:完成前的順序是從根部到子部,完成時時從子部到根部。(類似於事件機制)

  2. 每個組件的紅線(包括初次和更新)生命周期時一股腦執行完畢以后再執行低一級別的紅線生命周期。

  1. 第一級別的組件setState是不能觸發其父組件的生命周期更新函數,只能觸發更低一級別的生命周期更新函數。

總結起來就如下圖:


提問:
那么這里提一個問題,如果App里面有多個parent1 parent2 ...,parent里由多個child,那么生命周期執行順序應該時什么樣的????

結論:
一套組件(父包括子,子包括孫)執行的時候一個整體,執行完畢在執行下一套,用到這里就是App里先執行parent1和parent1的子,子的子。。。,然后完畢再執行parent2這一套。

三、什么時候該用componentWillReceiveProps?

是否每個子組件都需要componentWillReceiveProps生命周期函數來更新數據嗎? 你的原則是??

A、開始前首先需要知道componentWillReceiveProps函數有一個參數nextProps,它是一個 { 對象 } ,從單詞就可以看出它是update時候(也就是下一次)父組件傳遞過來的props。

B、還要知道 "第一條中" 所講解的有些生命周期函數只執行一次,而有的執行多次,其中componentWillReceiveProps執行多次,而constructor等執行一次。

C、還需知道在子組件中每次傳遞過來的this.props對象其實和componentWillReceiveProps的nextProps是一樣的,都是最新的。

D、由"第一條"得知: componentWillReceiveProps生命周期是在更新子組件最先執行的,優先於compoentWillUpdate,更優先於render。

E、render函數里不能使用setState(),否則會造成死循環。

那么知道了以上呢?

由C得知, this.props 和 componentWillReceiveProps的nextProps都是一樣的,通過this.props就可以取到最新的值, 那么componentWillReceiveProps還有必要嗎?

所以:大部分情況下 componentWillReceiveProps 生命周期函數是沒用的,即可以略去不寫,因為它確實沒什么用。

但是情況1:

由D得知,componentWillReceiveProps是最先執行的,所以在其內可以setState({}),在接下來的render中能拿到最新的state后值,再加上B得知,

如果是下面這種情況: 在constructor函數中初始化了某個state,必須用 componentWillReceiveProps 來更新state,以便render中為新的state值。


情況2:

  如果父組件有一些請求,每次參數更新的時候才發請求,同時和子組件的關系比較密切,

可以將數據請求放在componentWillReceiveProps進行執行,需要傳的參數則從(nextProps)中獲取。

而不必將所有的請求都放在父組件中,於是該請求只會在該組件渲染時才會發出,從而減輕請求負擔。

情況3:

  watch監聽props值變化,對子組件進行處理,比如:當傳入的props.value發生變化,執行一些動作。

  如果你接觸過vue,會知道vue中有一個關於watch的選項,是根據setter獲取新舊值,進行動作的執行

  而react中最合適做watch的時機是在componentWillReceiveProps中

componentWillReceiveProps(nextProps) {
        // this.props中的值是舊值
        // nextProps中的值是新值
    const { value: oldValue } = this.props;
    const { value: newValue } = nextProps;
    if (newValue !== oldValue) {
            // TODO...
    }
}

結論:

  1. 大部分情況下 componentWillReceiveProps 生命周期函數是沒用的,即可以略去不寫,

  2. 但是在constructor函數中初始化了某個state,必須用 componentWillReceiveProps 來更新state,不可省去,否則render中的state將得不到更新。
    同時如果您想在子組件監聽watch值變化做處理,也可以用到componentWillReceiveProps

  3. 使用componentWillReceiveProps的時候,不要去向上分發,調用父組件的相關setState方法,否則會成為死循環。

附:React生命周期官方解析

componentWillMount 在渲染前調用,在客戶端也在服務端。

componentDidMount : 在第一次渲染后調用,只在客戶端。之后組件已經生成了對應的DOM結構,可以通過this.getDOMNode()來進行訪問。 如果你想和其他JavaScript框架一起使用,可以在這個方法中調用setTimeout, setInterval或者發送AJAX請求等操作(防止異步操作阻塞UI)。

componentWillReceiveProps 在組件接收到一個新的 prop (更新后)時被調用。這個方法在初始化render時不會被調用。

shouldComponentUpdate 返回一個布爾值。在組件接收到新的props或者state時被調用。在初始化時或者使用forceUpdate時不被調用。 
可以在你確認不需要更新組件時使用。

componentWillUpdate在組件接收到新的props或者state但還沒有render時被調用。在初始化時不會被調用。

componentDidUpdate 在組件完成更新后立即調用。在初始化時不會被調用。

componentWillUnmount在組件從 DOM 中移除的時候立刻被調用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM