文章內容轉載於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)
結論:
-
如圖:完成前的順序是從根部到子部,完成時時從子部到根部。(類似於事件機制)
-
每個組件的紅線(包括初次和更新)生命周期時一股腦執行完畢以后再執行低一級別的紅線生命周期。
- 第一級別的組件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...
}
}
結論:
-
大部分情況下 componentWillReceiveProps 生命周期函數是沒用的,即可以略去不寫,
-
但是在constructor函數中初始化了某個state,必須用 componentWillReceiveProps 來更新state,不可省去,否則render中的state將得不到更新。
同時如果您想在子組件監聽watch值變化做處理,也可以用到componentWillReceiveProps -
使用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 中移除的時候立刻被調用。