所謂生命周期,就是一個對象從開始生成到最后消亡所經歷的狀態,理解生命周期,是合理開發的關鍵。RN 組件的生命周期整理如下圖:
如圖,可以把組件生命周期大致分為三個階段:
第一階段:是組件第一次繪制階段,如圖中的上面虛線框內,在這里完成了組件的加載和初始化;
第二階段:是組件在運行和交互階段,如圖中左下角虛線框,這個階段組件可以處理用戶交互,或者接收事件更新界面;
第三階段:是組件卸載消亡的階段,如圖中右下角的虛線框中,這里做一些組件的清理工作。
生命周期回調函數
下面來詳細介紹生命周期中的各回調函數。
getDefaultProps
在組件創建之前,會先調用 getDefaultProps()
,這是全局調用一次,嚴格地來說,這不是組件的生命周期的一部分。在組件被創建並加載候,首先調用 getInitialState()
,來初始化組件的狀態。
componentWillMount
然后,准備加載組件,會調用 componentWillMount()
,其原型如下:
void componentWillMount()
這個函數調用時機是在組件創建,並初始化了狀態之后,在第一次繪制 render()
之前。可以在這里做一些業務初始化操作,也可以設置組件狀態。這個函數在整個生命周期中只被調用一次。
componentDidMount
在組件第一次繪制之后,會調用 componentDidMount()
,通知組件已經加載完成。函數原型如下:
void componentDidMount()
這個函數調用的時候,其虛擬 DOM
已經構建完成,你可以在這個函數開始獲取其中的元素或者子組件了。需要注意的是,RN 框架是先調用子組件的 componentDidMount()
,然后調用父組件的函數。從這個函數開始,就可以和 JS 其他框架交互了,例如設置計時 setTimeout
或者 setInterval
,或者發起網絡請求,ajax
。這個函數也是只被調用一次。這個函數之后,就進入了穩定運行狀態,等待事件觸發。
componentWillReceiveProps
如果已加載組件收到新的參數屬性(props
),就會調用 componentWillReceiveProps()
,其原型如下:
void componentWillReceiveProps( object nextProps )
輸入參數 nextProps
是即將被設置的屬性,舊的屬性還是可以通過 this.props
來獲取。在這個回調函數里面,你可以根據屬性的變化,通過調用 this.setState()
來更新你的組件狀態,這里調用更新狀態是安全的,並不會觸發額外的 render()
調用。如下:
componentWillReceiveProps: function(nextProps) { this.setState({ likesIncreasing: nextProps.likeCount > this.props.likeCount }); }
shouldComponentUpdate
當組件接收到新的屬性和狀態改變的話,都會觸發調用 shouldComponentUpdate(...)
,函數原型如下:
boolean shouldComponentUpdate( object nextProps, object nextState )
輸入參數 nextProps
和上面的 componentWillReceiveProps
函數一樣,nextState 表示組件即將更新的狀態值。這個函數的返回值決定是否需要更新組件,如果 true
表示需要更新,繼續走后面的更新流程。否者,則不更新,直接進入等待狀態。
默認情況下,這個函數永遠返回 true
用來保證數據變化的時候 UI 能夠同步更新。在大型項目中,你可以自己重載這個函數,通過檢查變化前后屬性和狀態,來決定 UI 是否需要更新,能有效提高應用性能。 reactjs性能優化之shouldComponentUpdate
componentWillUpdate
如果組件狀態或者屬性改變,並且上面的 shouldComponentUpdate(...)
返回為 true,就會開始准更新組件,並調用 componentWillUpdate()
,其函數原型如下:
void componentWillUpdate( object nextProps, object nextState )
輸入參數與 shouldComponentUpdate
一樣,在這個回調中,可以做一些在更新界面之前要做的事情。需要特別注意的是,在這個函數里面,你就不能使用 this.setState
來修改狀態。這個函數調用之后,就會把 nextProps
和 nextState
分別設置到 this.props
和 this.state
中。緊接着這個函數,就會調用 render()
來更新界面了。
componentDidUpdate
調用了 render()
更新完成界面之后,會調用 componentDidUpdate()
來得到通知,其函數原型如下:
void componentDidUpdate( object prevProps, object prevState )
因為到這里已經完成了屬性和狀態的更新了,此函數的輸入參數變成了 prevProps
和 prevState
。
componentWillUnmount
當組件要被從界面上移除的時候,就會調用 componentWillUnmount()
,其函數原型如下:
void componentWillUnmount()
在這個函數中,可以做一些組件相關的清理工作,例如取消計時器、網絡請求等。
總結
到這里,RN 的組件的完整的生命都介紹完了,在回頭來看一下前面的圖,就比較清晰了,把生命周期的回調函數總結成如下表格:
生命周期 | 調用次數 | 能否使用 setSate() |
---|---|---|
getDefaultProps | 1(全局調用一次) | 否 |
getInitialState | 1 | 否 |
componentWillMount | 1 | 是 |
render | 大於1 | 否 |
componentDidMount | 1 | 是 |
componentWillReceiveProps | 大於0 | 是 |
shouldComponentUpdate | 大於0 | 否 |
componentWillUpdate | 大於0 | 否 |
componentDidUpdate | 大於0 | 否 |
componentWillUnmount | 1 | 否 |