前段时间一直在基于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直接调用方法