一個 React Native
組件從它被加載,到最終被卸載熄驼,會經(jīng)歷一個完整的生命周期蛤售。
在這個生命周期中,框架已經(jīng)為我們定義了一些生命周期函數(shù)喂江,用來處理在特定條件下 React Native
組件將要執(zhí)行的操作召锈,比如在某個時間進行數(shù)據(jù)初始化或進行網(wǎng)絡(luò)請求等。
一获询、組件的生命周期
組件的生命周期一般分為4個階段:創(chuàng)建階段
涨岁、實例化階段
、運行(更新)階段
和銷毀階段
筐付。下面對各個階段分別進行介紹卵惦。
1. 創(chuàng)建階段
- 該階段主要發(fā)生在創(chuàng)建組件類的時候,在這個階段會初始化組件的屬性類型
propTypes
和默認值defaultProps
瓦戚。當調(diào)用該組件時,只要看創(chuàng)建階段的屬性聲明丛塌,即可知道如何調(diào)用较解。 - 在 ES6 中統(tǒng)一使用
static
成員來實現(xiàn)畜疾。
// 聲明屬性類型
static propTypes = {
name: PropTypes.string,
};
// 聲明屬性默認值
static defaultProps = {
name: 'xiaowang'
};
備注1:出于性能原因,
propTypes
類型僅在develop
模式下進行檢查印衔,production
環(huán)境下不檢查啡捶。
備注2:RN官方推薦以組件的方式來重用代碼,而不是繼承奸焙。所以瞎暑,在實際開發(fā)中,應(yīng)多封裝組件与帆,并寫清楚組件需要傳入的參數(shù)類型聲明了赌,方便調(diào)用。
2. 實例化階段
該階段主要發(fā)生在實例化組件的時候玄糟,創(chuàng)建組件勿她,準備渲染,渲染阵翎,渲染完成逢并。
調(diào)用的函數(shù)順序如下:
-
constructor
:構(gòu)造函數(shù),對組件的狀態(tài)進行初始化郭卫。 -
componentWillMount
:準備加載組件砍聊,可以做一些業(yè)務(wù)初始化工作或設(shè)置組件狀態(tài)。 -
render
:生成頁面需要的DOM結(jié)構(gòu)贰军,并返回玻蝌。 -
componentDidMount
: 組件加載成功并被成功渲染后執(zhí)行。一般講網(wǎng)絡(luò)請求等獲取數(shù)據(jù)比較耗時的操作放在這里進行谓形,保證UI渲染不出現(xiàn)錯誤灶伊。
3. 運行(更新)階段
該階段主要發(fā)生在用戶操作之后或者父組件有更新的時候,此時會根據(jù)用戶的操作行為進行相應(yīng)的頁面結(jié)構(gòu)的調(diào)整寒跳。這個階段也會觸發(fā)一系列的流程聘萨,按執(zhí)行順序如下:
-
componentWillReceiveProps
:當組件接收到新的 props 時,會觸發(fā)該函數(shù)童太。在該函數(shù)中米辐,通常可以調(diào)用 this.setState 方法來完成對 state 的修改书释。 -
shouldComponentUpdate
:該方法用來攔截新的 props 或 state翘贮,然后根據(jù)事先設(shè)定好的判斷邏輯,做出最后要不要更新組件的決定爆惧。 -
componentWillUpdate
:當上面的方法攔截返回 true 的時候狸页,就可以在該方法中做一些更新之前的操作。 -
render
:根據(jù)一系列的 diff 算法,生成需要更新的虛擬 DOM 數(shù)據(jù)芍耘。(注意:在 render 中最好只做數(shù)據(jù)和模板的組合址遇,不應(yīng)進行 state 等邏輯的修改,這樣組件結(jié)構(gòu)會更加清晰) -
componentDidUpdate
:該方法在組件的更新已經(jīng)同步到 DOM 中去后觸發(fā)斋竞,我們常在該方法中做 DOM 操作倔约。
4. 銷毀階段
該階段主要在組件銷毀的時候觸發(fā)。
-
componentWillUnmount
:當組件要被從界面上移除時就會調(diào)用坝初〗#可以在這個函數(shù)中做一些相關(guān)的清理工作,例如取消計時器鳄袍、網(wǎng)絡(luò)請求以及移除通知監(jiān)聽等绢要。
流程圖;
二畦木、生命周期函數(shù)詳細介紹
1. constructor
(1)函數(shù)原型
constructor(props) {
super(props);
this.state = {}
}
(2)基本介紹
- 它是組件的構(gòu)造函數(shù)袖扛。它的第一個語句必須是
super(props)
,參數(shù)props
值為外界傳入的屬性十籍,所以這里可以直接使用props
值來初始化state
蛆封。 - 構(gòu)造函數(shù)將在組件被加載前最先調(diào)用,并且僅調(diào)用一次勾栗。
(3)常見用途
構(gòu)造函數(shù)最大的作用惨篱,就是在這里定義狀態(tài)機變量。
2. componentWillMount
(1)函數(shù)原型
componentWillMount() {
console.log('componentWillMount');
}
(2)基本介紹
- 在組件的生命周期中围俘,這個函數(shù)只會被執(zhí)行一次砸讳,從下個頁面返回到當前頁面也不會再調(diào)用。
- 它在初始渲染(
render
函數(shù)被React Native
框架調(diào)用執(zhí)行)前被執(zhí)行界牡,當它執(zhí)行完后簿寂,render
函數(shù)會馬上被React Native
框架調(diào)用執(zhí)行。 - 如果子組件也有
componentWillMount
函數(shù)宿亡,它會在父組件的componentWillMount
函數(shù)之后被調(diào)用常遂。
(3)常見用途
如果我們需要從本地存儲中讀取數(shù)據(jù)用于顯示,那么在這個函數(shù)里進行讀取是一個很好的時機挽荠。
注意:如果在這個函數(shù)里調(diào)用
setstate
函數(shù)改變了某些狀態(tài)機變量的值克胳,React Native
框架不會執(zhí)行渲染操作,而是等待這個函數(shù)執(zhí)行完成后再執(zhí)行初始渲染圈匆。
3. render
(1)函數(shù)原型
render() {
return (
<View style={styles.container}>
<Text>{this.state.name}</Text>
</View>
)
}
(2)基本介紹
-
render
是一個組件必須有的方法漠另,用于界面渲染。 - 這個函數(shù)無參數(shù)跃赚,返回
JSX
或者其他組件來構(gòu)成DOM
笆搓。注意:只能返回一個頂級元素。
4. componentDidMount
(1)函數(shù)原型
componentDidMount() {
console.log('componentDidMount');
}
(2)基本介紹
- 在組件的生命周期中,這個函數(shù)只會被執(zhí)行一次砚作。
- 它在初始渲染執(zhí)行完成后會馬上被調(diào)用窘奏。在組件生命周期的這個時間點之后嘹锁,開發(fā)者可以通過子組件的引用來訪問葫录、操作任何子組件。
- 如果子組件也有
componentDidMount
函數(shù)领猾,它會在父組件的componentDidMount
函數(shù)之前被調(diào)用米同。
(3)常見用途
如果 React Native 應(yīng)用需要在程序啟動并顯示初始界面后從網(wǎng)絡(luò)側(cè)獲取數(shù)據(jù),那么把從網(wǎng)絡(luò)側(cè)獲取數(shù)據(jù)的代碼放在這個函數(shù)里是一個不錯的選擇摔竿。
5. componentWillReceiveProps
(1)函數(shù)原型
componentWillReceiveProps(nextProps) {
if (nextProps.name != this.state.name) {
this.setState({
name: nextProps.name
})
}
}
(2)基本介紹
- 組件的初始渲染執(zhí)行完成后面粮,當組件接收到新的
props
時,這個函數(shù)將被調(diào)用继低。 - 這個函數(shù)不需要返回值熬苍。接收一個
object
參數(shù),object
里是新的props
袁翁。 - 如果新的
props
會導致界面重新渲染柴底,這個函數(shù)將在渲染前被執(zhí)行。在這個函數(shù)中粱胜,老的props
可以通過this.props
訪問柄驻,新的props
在傳入的object
中。 - 如果在這個函數(shù)中通過調(diào)用
this.setState
函數(shù)改變某些狀態(tài)機變量的值焙压,React Native
框架不會執(zhí)行對這些狀態(tài)機變量改變的渲染鸿脓,而是等componentWillReceiveProps
函數(shù)執(zhí)行完成后一起渲染。
注意:當
React Native
初次被渲染時涯曲,componentWillReceiveProps
函數(shù)并不會被觸發(fā)野哭,這種機制是故意設(shè)計的。
6. shouldComponentUpdate
(1)函數(shù)原型
shouldComponentUpdate(nextProps, nextState) {
// nextProps 最新的屬性
// nextState 將要渲染的狀態(tài)
return true;
}
(2)基本介紹
- 組件的初始渲染執(zhí)行完成后幻件,當組件接收到新的
state
或者props
時這個函數(shù)將被調(diào)用拨黔。 - 該函數(shù)接收兩個
object
參數(shù),其中第一個是新的props
傲武,第二個是新的state
蓉驹。 - 該函數(shù)需要返回一個布爾值,告訴
React Native
框架針對這次改變揪利,是否需要重新渲染本組件态兴。默認返回true
。如果此函數(shù)返回false
疟位,React Native
將不會重新渲染本組件瞻润,相應(yīng)的,該組件的componentWillUpdate
和componentDidUpdate
函數(shù)也不會被調(diào)用。
(3)常見用途
這個函數(shù)常常用來阻止不必要的重新渲染绍撞,提高 React Native
應(yīng)用程序性能正勒。
比如我們可以在該函數(shù)中比較新老版本的 state
和 props
,判斷是否需要進行重新渲染傻铣。下面是一個簡單的使用樣例:
shouldComponentUpdate(nextProps, nextState) {
if(this.state.inputedNum.length < 3) return false;
return true;
}
7. componentWillUpdate
(1)函數(shù)原型
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate');
}
(2)基本介紹
- 組件的初始渲染執(zhí)行完成后章贞,
React Native
框架在重新渲染該組件前會調(diào)用這個函數(shù)。 - 該函數(shù)不需要返回值非洲,接收兩個
object
參數(shù)鸭限,其中第一個是新的props
,第二個是新的state
两踏。 - 我們可以在這個函數(shù)中為即將發(fā)生的重新渲染做一些準備工作败京,但不能在這個函數(shù)中通過
this.setState
再次改變狀態(tài)機變量的值。如果需要改變梦染,則在componentWillReceiveProps
函數(shù)中進行改變赡麦。
8. componentDidUpdate
(1)函數(shù)原型
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate');
}
(2)基本介紹
-
React Native
框架在重新渲染該組件完成后會調(diào)用這個函數(shù)(組件第一次渲染執(zhí)行完成后不調(diào)用該函數(shù))。 - 該函數(shù)不需要返回值帕识,接收兩個
object
參數(shù)泛粹,其中第一個是渲染前的props
,第二個是渲染前的state
渡冻。
9. componentWillUnmount
(1)函數(shù)原型
componentWillUnmount() {
console.log('componentWillUnmount');
}
(2)基本介紹
- 在組件被卸載前戚扳,這個函數(shù)將被執(zhí)行。
- 這個函數(shù)沒有參數(shù)族吻,也沒不需要返回值帽借。
(3)常見用途
如果組件申請了某些資源或者訂閱了某些消息,那么需要在這個函數(shù)中釋放資源超歌,取消訂閱砍艾。
三、舉例
1.示例代碼:
'use strict';
import React, { Component, PropTypes } from 'react';
import {
View,
Text,
Button,
StyleSheet,
AppRegistry
} from 'react-native';
class LifecycleClass extends Component {
// 聲明屬性類型
static propTypes = {
name: PropTypes.string,
};
// 聲明屬性默認值
static defaultProps = {
name: 'xiaowang'
};
constructor(props) {
// 初始化(只調(diào)用一次)
super(props);
this.state = {
name: props.name
}
}
componentWillMount() {
// 組件將要加載(只調(diào)用一次)
}
componentDidMount() {
// 組件已經(jīng)加載(只調(diào)用一次)
}
componentWillReceiveProps(nextProps) {
// 組件接收到外部屬性改變(屬性改變時調(diào)用巍举,可調(diào)用多次)
if (nextProps.name != this.state.name) {
this.setState({
name: nextProps.name
})
}
}
shouldComponentUpdate(nextProps, nextState) {
// 組件是否要刷新 nextProps: 最新的屬性 nextState: 將要渲染的狀態(tài)
return true;
}
componentWillUpdate(nextProps, nextState) {
// 組件將要刷新
}
componentDidUpdate(prevProps, prevState) {
// 組件已經(jīng)刷新
}
componentWillUnmount() {
// 組件將要卸載
}
render() {
// 渲染組件
return (
<View style={styles.container}>
<Text>{this.state.name}</Text>
</View>
)
}
}
2.執(zhí)行結(jié)果:
// --------------初次渲染--------------
// 打印結(jié)果:
constructor
componentWillMount
render
componentDidMount
// --------------外部修改name屬性--------------
// 打印結(jié)果:
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
// --------------關(guān)閉該組件--------------
componentWillUnmount
demo地址:RN組件生命周期demo
后記:本人工作中使用的就是RN脆荷,雖然已經(jīng)很熟練,但在工作中發(fā)現(xiàn)還有知識點遺漏懊悯,所以想寫一個系列文章蜓谋,把所有知識點再過一遍,以達到復習查缺補漏的效果炭分。文章中很多內(nèi)容都是借鑒別人的桃焕,但不是完全盲目照搬,取其精華去其糟粕捧毛,我把該有的知識點都帶上观堂,再加上自己的理解让网,目標就是將一個知識點講明白,理清楚师痕,并配上自己在實際使用過程中遇到的坑溃睹,幫助自己和大家日后參考。
注:如有雷同胰坟,純屬我抄的因篇!哈哈