React生命周期

React生命周期分為15和16兩個不同的版本

React15生命周期

image.png

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生命周期

image.png

新引入了兩個新的生命周期函數

  • 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()。

參考自

//www.jianshu.com/p/b331d0e4b398

//www.jianshu.com/p/2b2d1da16947

Tags: