前段時間一直在基於React做開發,最近得空做一些總結,防止以后踩坑。
言歸正傳,React生命周期是React組件運行的基礎,本文主要是歸納多組件平行、嵌套時,生命周期轉換關系。
生命周期
React生命周期中有如下幾種轉換方式:
類調用:
此過程僅在類創建時被一次,即無論創建多少個ReactElement,此過程均只會執行一次
- getDefaultProps
實例化:
此過程僅執行一次,執行完畢后,React組件真正被渲染到DOM中
期間執行生命周期函數如下:
- getInitialState
- componentWillMount
- render
- componentDidMount
變更:
此過程會在this.state
或this.props
變更時執行
期間執行生命周期函數如下:
-
this.state變更
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
-
this.props變更
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
卸載:
此過程在組件銷毀前調用一次
期間執行生命周期函數如下:
- componentWillUnmount
整個生命周期所涉及的方法如圖所示:
測試多組件生命周期轉換
以上描述了單個組件內部生命周期轉換過程,但實際開發中,組件往往存在着平行或嵌套的關系,這時候,只了解單個組件的運行過程是不夠的,下面通過不同場景,歸納多組件生命周期的轉換關系。
測試demo如下(github:https://github.com/hhhyaaon/react-lifecycle-demo):
- 父組件Component_Super,子組件Component_Sub_1和Component_Sub_2平行
- Component_Super含
this.state.count
,按鈕每點擊一次 count+1 - Component_Sub_1和Component_Sub_2含
this.state.count
,按鈕每點擊一次 count+1; - Component_Sub_1含
this.props.count
,值為Component_Super中this.state.count
;
實例化周期
頁面加載后,觀察控制台輸出:
- 執行
getDefaultProps
方法- 三組件中,此方法首先被執行
getDefaultProps
屬於組件類方法,而非組件實例方法,在組件類定義后執行;即:只要此class被定義,無論是否使用,無論使用多少次,其中定義的getDefaultProps
方法都會被執行,且僅執行一次
- 父組件Super執行
componentDidMount
- 父組件的
componentDidMount
方法會在其render的全部內容裝載到DOM后執行,若父組件中包含定義的子組件,則componentDidMount
方法會在子組件執行完實例化周期后再執行
- 父組件的
- 子組件Sub1、Sub2執行
componentDidMount
- 多個子組件平行,並非依次執行實例化周期(getInitialState->componentWillMount->render->componentDidMount),而是待所有所有平行子組件首次render后,再依次執行
componentDidMount
- 多個子組件平行,並非依次執行實例化周期(getInitialState->componentWillMount->render->componentDidMount),而是待所有所有平行子組件首次render后,再依次執行
更新期
點擊Sub1/Sub2中[count+1]按鈕
- Sub1執行更新期方法
- 所有執行的方法均為Sub1組件周期方法,而不行執行其平行組件Sub2及父組件Super中的方法
點擊Super中[count+1]按鈕
- Super執行更新期方法
- state變化觸發Super依次執行更新期方法(shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate),其中
componentDidUpdate
會在全部子組件更新完畢后執行
- state變化觸發Super依次執行更新期方法(shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate),其中
- Sub1、Sub2執行更新期方法
- Sub1接收父組件值
this.props.count
,而Sub2未接收任何父組件傳值,但兩子組件的componentWillReceiveProps
都被執行,故只要當前組件作為子組件渲染,注冊了componentWillReceiveProps
,此方法都會在父組件變更后執行 - 盡管Sub2未接收任何父組件傳值,但當Super更新時,Sub2仍執行了整個更新期的方法,故父組件的變更會導致其下所有子組件進入更新期
- Sub1接收父組件值
卸載期
點擊卸載Sub1
- Super執行更新期方法
- state變化觸發Super依次執行更新期方法(shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate)
- Sub1執行卸載期方法
- Sub1進入卸載期后,僅執行
componentWillUnmount
,並在所有同級組件render
后執行
- Sub1進入卸載期后,僅執行
點擊卸載Super
- Sub1、Sub2依次執行
componentWillUnmount
- Super執行
componentWillUnmount
- 由於卸載Super直接調用方法
ReactDOM.unmountComponentAtNode()
,故並未執行Super的componentWillUnmount
方法;但若是通過狀態變更將Super卸載,其componentWillUnmount
方法將會在Sub1、Sub2執行componentWillUnmount
前執行
- 由於卸載Super直接調用方法