ReactNative 进阶(十六):React-Native 组件生命周期
概述
所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解生命周期,是合理开发的关键。RN 组件的生命周期整理如下图:
如图,可以把组件生命周期大致分为三个阶段:
第一阶段:是组件第一次绘制阶段,如图中的上面虚线框内,在这里完成了组件的加载和初始化;
第二阶段:是组件在运行和交互阶段,如图中左下角虚线框,这个阶段组件可以处理用户交互,或者接收事件更新界面;
第三阶段:是组件卸载消亡的阶段,如图中右下角的虚线框中,这里做一些组件的清理工作。
一、组件的生命周期
组件的生命周期一般分为 4 个阶段:创建阶段、实例化阶段、运行(更新)阶段、销毁阶段
。下面对各个阶段分别进行介绍。
1.1 创建阶段
该阶段主要发生在创建组件类的时候,在这个阶段中会初始化组件的属性类型和默认属性。通常会将固定的内容放在这个过程中进行初始化和赋值。在 ES6
中统一使用 static
成员来实现。
1.2 实例化阶段
该阶段主要发生在实例化组件类的时候,也就是该组件类被调用的时候触发。这个阶段会触发一系列的流程,按执行顺序如下:
constructor
:构造函数,这里主要对组件的一些状态进行初始化。
componentWillMount
:准备加载组件,可以在这里做一些业务初始化操作,或者设置组件状态。
render
:生成页面需要的DOM
结构,并返回该结构。
componentDidMount
:组件加载成功并被成功渲染出来后执行。一般会将网络请求等加载数据的操作放在这里进行,保证不会出现UI
上的错误。
1.3 运行(更新)阶段
该阶段主要发生在用户操作之后或者父组件有更新的时候,此时会根据用户的操作行为进行相应的页面结构调整。这个阶段也会触发一系列的流程,按执行顺序如下:
componentWillReceiveProps
:当组件接收到新的props
时,会触发该函数。在该函数中,通常可以调用this.setState
方法来完成对state
的修改。
shouldComponentUpdate
:该方法用来拦截新的props
或state
,然后根据事先设定好的判断逻辑,做出最后要不要更新组件的决定。
componentWillUpdate
:当上面的方法拦截返回true
的时候,就可以在该方法中做一些更新之前的操作。
render
:根据一系列的diff
算法,生成需要更新的虚拟 DOM
数据。(注意:在render
中最好只做数据和模板的组合,不应进行state
等逻辑的修改,这样组件结构会更加清晰)
componentDidUpdate
:该方法在组件的更新已经同步到DOM
中去后触发,常在该方法中做DOM
操作。
1.4 销毁阶段
该阶段主要在组件消亡的时候触发。
componentWillUnmount
:当组件要被从界面上移除时就会调用。可以在这个函数中做一些相关的清理工作,例如取消计时器、网络请求等。
二、生命周期函数详细介绍
下面来详细介绍生命周期中的各回调函数。
constructor
(1)函数原型
(2)基本介绍它是组件的构造函数。它的第一个语句必须是 super(props)
。构造函数将在组件被加载前最先调用,并且仅调用一次。
(3)常见用途构造函数最大的作用,就是在这里定义状态机变量。
getDefaultProps
在组件创建之前,会先调用 getDefaultProps()
,全局调用一次。严格来说,这不是组件生命周期的一部分。在组件被创建并加载后,首先调用 getInitialState()
,来初始化组件的状态。
componentWillMount
然后,准备加载组件,会调用 componentWillMount()
,其原型如下:
这个函数调用时机是在组件创建,并初始化状态之后,在第一次绘制 render()
之前。
(2)基本介绍
在组件的生命周期中,这个函数只会被执行一次。
这个函数无参数并且不需要任何返回值。
它在初始渲染(
render
函数被React Native
框架调用执行)前被执行,当它执行完后,render
函数会马上被React Native
框架调用执行。注意:如果在这个函数里调用setstate
函数改变了某些状态机变量的值,React Native
框架不会执行渲染操作,而是等待这个函数执行完成后再执行初始渲染。如果子组件也有
componentWillMount
函数,它会在父组件的componentWillMount
函数之后被调用。
(3)常见用途如果我们需要从本地存储中读取数据用于显示,那么在这个函数里进行读取是一个很好的时机。可以在这里做一些业务初始化操作,也可以设置组件状态。
render
(1)函数原型
(2)基本介绍render
是一个组件必须有的方法,用于界面渲染。这个函数无参数,返回 JSX
或者其他组件来构成 DOM
。
注意:只能返回一个顶级元素。
componentDidMount
在组件第一次绘制之后,会调用 componentDidMount()
,通知组件已经加载完成。函数原型如下:
这个函数调用的时候,其虚拟 DOM
已经构建完成,你可以在这个函数开始获取其中的元素或者子组件。需要注意的是,RN 框架是先调用子组件的 componentDidMount()
,然后调用父组件的函数。从这个函数开始,就可以和 JS 其他框架交互了,例如设置计时 setTimeout
或者 setInterval
,或者发起网络请求。这个函数也是只被调用一次。这个函数之后,就进入了稳定运行状态,等待事件触发。
(2)基本介绍
在组件的生命周期中,这个函数只会被执行一次。
这个函数无参数并且不需要任何返回值。
它在初始渲染执行完成后会马上被调用。在组件生命周期的这个时间点之后,开发者可以通过子组件的引用来访问、操作任何子组件。
如果子组件也有
componentDidMount
函数,它会在父组件的componentDidMount
函数之前被调用。
(3)常见用途如果 React Native
应用需要在程序启动并显示初始界面后从网络侧获取数据,那么把从网络侧获取数据的代码放在这个函数里是一个不错的选择。
componentWillReceiveProps
如果组件收到新的属性(props
),就会调用 componentWillReceiveProps()
,其原型如下:
输入参数 nextProps
是即将被设置的属性,旧的属性还是可以通过 this.props
来获取。在这个回调函数里面,可以根据属性变化,通过调用 this.setState()
来更新组件状态,这里调用更新状态是安全的,并不会触发额外的 render()
调用。如下:
(2)基本介绍
组件的初始渲染执行完成后,当组件接收到新的
props
时,这个函数将被调用。这个函数不需要返回值。接收一个
object
参数,object
里是新的props
。如果新的
props
会导致界面重新渲染,这个函数将在渲染前被执行。在这个函数中,老的props
可以通过this.props
访问,新的props
在传入的object
中。如果在这个函数中通过调用
this.setState
函数改变某些状态机变量的值,React Native
框架不会执行对这些状态机变量改变的渲染,而是等componentWillReceiveProps
函数执行完成后一起渲染。
注意: 当
React Native
初次被渲染时,componentWillReceiveProps
函数并不会被触发,这种机制是故意设计的。
shouldComponentUpdate
当组件接收到新的属性和状态改变,都会触发调用 shouldComponentUpdate(...)
,函数原型如下:
输入参数 nextProps
和上面的 componentWillReceiveProps
函数一样,nextState
表示组件即将更新的状态值。这个函数的返回值决定是否需要更新组件,如果 true
表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。
默认情况下,这个函数永远返回 true
用来保证数据变化的时候 UI
能够同步更新。在大型项目中,可以自己重载这个函数,通过检查变化前后属性和状态,来决定 UI
是否需要更新,有效提高应用性能。
(2)基本介绍
组件初始渲染执行完成后,当组件接收到新的
state
或者props
时这个函数将被调用。该函数接收两个
object
参数,其中第一个是新的props
,第二个是新的state
。该函数需要返回一个布尔值,告诉
React Native
框架针对这次改变,是否需要重新渲染本组件。默认返回true
。如果此函数返回false
,React Native
将不会重新渲染本组件,相应的,该组件的componentWillUpdate
和componentDidUpdate
函数也不会被调用。
(3)常见用途这个函数常常用来阻止不必要的重新渲染,提高 React Native
应用程序性能。比如我们可以在该函数中比较新老版本的 state
和 props
,判断是否需要进行重新渲染。下面是一个简单的使用样例:
componentWillUpdate
如果组件状态或者属性改变,并且上面的 shouldComponentUpdate(...)
返回为 true
,就会开始准更新组件,并调用 componentWillUpdate()
,其函数原型如下:
输入参数与 shouldComponentUpdate
一样,在这个回调中,可以做一些在更新界面之前要做的事情。需要特别注意的是,在这个函数里面,不能使用 this.setState
来修改状态。这个函数调用之后,就会把 nextProps
和 nextState
分别设置到 this.props
和 this.state
中。紧接着这个函数,就会调用 render()
来更新界面。
(2)基本介绍
组件初始渲染执行完成后,
React Native
框架在重新渲染该组件前会调用这个函数。该函数不需要返回值,接收两个
object
参数,其中第一个是新的props
,第二个是新的state
。可以在这个函数中为即将发生的重新渲染做一些准备工作,但不能在这个函数中通过
this.setState
再次改变状态机变量的值。如果需要改变,则在componentWillReceiveProps
函数中进行改变。
componentDidUpdate
调用了 render()
更新完成界面之后,会调用 componentDidUpdate()
来得到通知,其函数原型如下:
到这里,就完成了属性和状态的更新,此函数的输入参数变成了 prevProps
和 prevState
。
基本介绍
组件初始渲染执行完成后,
React Native
框架在重新渲染该组件完成后会调用这个函数。该函数不需要返回值,接收两个
object
参数,其中第一个是渲染前的props
,第二个是渲染前的state
。
componentWillUnmount
当组件要被从界面上移除的时候,就会调用 componentWillUnmount()
,其函数原型如下:
在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。
(2)基本介绍
在组件被卸载前,这个函数将被执行。
这个函数没有参数,也没不需要返回值。
(3)常见用途如果组件申请了某些资源或者订阅了某些消息,那么需要在这个函数中释放资源,取消订阅。
三、完整样例
下面通过一个简单的文本显示组件,来演示组件各个环节的运作流程。同时这里把组件整个生命周期中所有会触发的方法罗列出来。
控制台输出信息如下(由于样例中没有更新状态,也没有销毁组件。所以也就没有后面两个阶段):
四、总结
到这里,RN 组件完整的生命介绍完毕,回过头来看一下前面的图,就比较清晰了,把生命周期的回调函数总结成如下表格:
版权声明: 本文为 InfoQ 作者【华强】的原创文章。
原文链接:【http://xie.infoq.cn/article/1f11f559ac43e4554fef23b83】。文章转载请联系作者。
评论