React生命周期
React生命周期分為15和16兩個不同的版本
React15生命周期
React15有四個不同的階段
- 初始化(initialization)
- 掛載階段(Mounting)
- 更新階段(Updating)
- 卸載階段
初始化
constructor()
- 組件一創建就會調用 es6 class類中的 constructor 方法(最先執行)
- super(props)`用來調用類的構造方法( constructor() ), 也將父組件的props注入給子組件,子組件中props只讀不可變,state可變
- constructor()用來做一些組件的初始化工作,如定義this.state的初始內容
掛載階段
componentWillMount()
在組件掛載到DOM前調用,且只會被調用一次,在這邊調用this.setState不會引起組件重新渲染,也可以把寫在這邊的內容提前到constructor()中,所以項目中很少用,它代表的過程是組件已經經歷了constructor()初始化數據後,但是還未渲染DOM時。
render()
根據組件的props和state(兩者的重傳遞和重賦值,無論值是否有變化,都可以引起組件重新render) ,當父組件的 render 函數被運行時, 它的子組件的 render 函數也會被重新運行
return 一個React元素(描述組件,即JSX模板),不負責組件實際渲染工作,之後由React自身根據此元素去渲染出頁面DOM。render是純函數(Pure function:函數的返回結果只依賴於它的參數;函數執行過程裡面沒有副作用),不能在裡面執行this.setState,會有改變組件狀態的副作用。
componentDidMount()
組件掛載到DOM後調用,且只會被調用一次
更新階段
componentWillReceiveProps(nextProps)
- 只跟父組件傳過來的 props 的變化有關,所以只有能接受 props 參數的子組件才有這個方法
- 此方法只調用於props引起的組件更新過程中,參數nextProps是父組件傳給當前組件的新props
- 而且這個組件第一次存在於父組件的是時候不會被執行(就是第一次不會執行,以後如果 nextProps 參數有變化才會被執行
shouldComponentUpdate(nextProps, nextState)
- 主要用於性能優化(部分更新)
- 唯一用於控制組件重新渲染的生命周期,由於在react中,setState以後,state發生變化,組件會進入重新渲染的流程,在這裡return false可以阻止組件的更新
- 因為react父組件的重新渲染會導致其所有子組件的重新渲染,這個時候其實我們是不需要所有子組件都跟著重新渲染的,因此需要在子組件的該生命周期中做判斷
componentWillUpdate(nextProps, nextState)
在調用render方法前執行,在這邊可執行一些組件更新發生前的工作,一般較少用
render
componentDidUpdate(prevProps, prevState)
此方法在組件更新後被調用,可以操作組件更新的DOM,prevProps和prevState這兩個參數指的是組件更新前的props和state
卸載階段
componentWillUnmount
此方法在組件被卸載前調用,可以在這裡執行一些清理工作,比如清楚組件中使用的定時器,清楚componentDidMount中手動創建的DOM元素等,以避免引起記憶體泄漏。
React16生命周期
新引入了兩個新的生命周期函數
- getDerivedStateFromProps(nextProps, prevState)
- getSnapshotBeforeUpdate(prevProps, prevState)
getDerivedStateFromProps(nextProps, prevState)
- 它應該返回一個對象來更新狀態,或者返回null來不更新任何內容
- 代替componentWillReceiveProps()。老版本中的componentWillReceiveProps()方法判斷前後兩個 props 是否相同,如果不同再將新的 props 更新到相應的 state 上去。這樣做一來會破壞 state 數據的單一數據源,導致組件狀態變得不可預測,另一方面也會增加組件的重繪次數。在 componentWillReceiveProps 中,我們一般會做以下兩件事,一是根據 props 來更新 state,二是觸發一些回調,如動畫或頁面跳轉等。在老版本的 React 中,這兩件事我們都需要在 componentWillReceiveProps 中去做。而在新版本中,官方將更新 state 與觸發回調重新分配到了 getDerivedStateFromProps 與 componentDidUpdate 中,使得組件整體的更新邏輯更為清晰。而且在 getDerivedStateFromProps 中還禁止了組件去訪問 this.props,強制讓開發者去比較 nextProps 與 prevState 中的值,以確保當開發者用到 getDerivedStateFromProps 這個生命周期函數時,就是在根據當前的 props 來更新組件的 state,而不是去做其他一些讓組件自身狀態變得更加不可預測的事情
getSnapshotBeforeUpdate(prevProps, prevState)
代替componentWillUpdate。常見的 componentWillUpdate 的用例是在組件更新前,讀取當前某個 DOM 元素的狀態,並在 componentDidUpdate 中進行相應的處理。
這兩者的區別在於:
- 在 React 開啟非同步渲染模式後,在 render 階段讀取到的 DOM 元素狀態並不總是和 commit 階段相同,這就導致在componentDidUpdate 中使用 componentWillUpdate 中讀取到的 DOM 元素狀態是不安全的,因為這時的值很有可能已經失效了。
- getSnapshotBeforeUpdate 會在最終的 render 之前被調用,也就是說在 getSnapshotBeforeUpdate 中讀取到的 DOM 元素狀態是可以保證與 componentDidUpdate 中一致的。
此生命周期返回的任何值都將作為參數傳遞給componentDidUpdate()。
參考自