React Native 組件生命周期 ----ES6

在React Native中使用組件來封裝界面模塊時,整個界面就是一個大的組件,開發(fā)過程就是不斷優(yōu)化和拆分界面組件、構(gòu)造整個組件樹的過程。

所以學習理解組件的生命周期顯得尤為重要!

一、組件的屬性(props)和狀態(tài)(state)

1. 屬性(props)

它是組件的不可變屬性(組件自己不可以自己修改props,只可由其他組件調(diào)用它時在外部改變)。

組件自身定義了一組props作為對外提供的接口,展示一個組件時只需要指定props作為節(jié)點的屬性。

一般組件很少需要對外公開方法(例外:工具類的靜態(tài)方法等),唯一的交互途徑就是props。所以說它也是父組件與子組件通信的橋梁

組件自己不可以自己修改props(即:props可認為是只讀的),只可由其他組件調(diào)用它時在外部修改。

2. 狀態(tài)(state)

它是組件的內(nèi)部狀態(tài)屬性,主要用來存儲組件自身需要的數(shù)據(jù)。

除了初始化時可能由props來決定,之后就完全由組件自身去維護。

組件中由系統(tǒng)定義了setState方法,每次調(diào)用setState時都會更新組件的狀態(tài),觸發(fā)render方法重新渲染界面

需要注意的是render方法是被異步調(diào)用的,這可以保證同步的多個setState方法只會觸發(fā)一次render,這樣做是有利于提高性能的。

二、組件的生命周期

對于自定義組件,除了必須實現(xiàn)的render方法,還有一些其他的可選方法可被調(diào)用。這些方法會在組件的不同時期之行,所以也可以說這些方法是組件的生命周期方法。

對于組件的生命周期來說一般分為四個階段,分別為:

創(chuàng)建階段、實例化階段、運行(更新)階段、銷毀階段。

1. 創(chuàng)建階段

該階段主要發(fā)生在創(chuàng)建組件類的時候,在這個階段中會初始化組件的屬性類型和默認屬性。

defaultProps / getDefaultProps()

這里會初始化一些默認的屬性,通常會將固定的內(nèi)容放在這個過程中進行初始化和賦值,一個控件可以利用this.props獲取在這里初始化它的屬性,由于組件初始化后,再次使用該組件不會調(diào)用getDefaultProps函數(shù),所以組件自己不可以自己修改props(即:props可認為是只讀的),只可由其他組件調(diào)用它時在外部修改。

在ES5里,屬性類型和默認屬性分別通過propTypes成員和getDefaultProps方法來實現(xiàn)。

//ES5

propTypes: {

autoPlay: React.PropTypes.bool.isRequired,

maxLoops: React.PropTypes.number.isRequired,

posterFrameSrc: React.PropTypes.string.isRequired,

videoSrc: React.PropTypes.string.isRequired,

},

getDefaultProps: function() {? ? ? ??

? ? ? ? ? ? ? ?return {? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? autoPlay: false,? ? ? ? ? ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?maxLoops: 10,? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ?};

},

在ES6里,可以統(tǒng)一使用static成員來實現(xiàn).

//ES6

static?propTypes?=?{//用來指定props的類型

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? autoPlay:?React.PropTypes.bool.isRequired,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?maxLoops:?React.PropTypes.number.isRequired,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?posterFrameSrc:?React.PropTypes.string.isRequired,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? videoSrc:?React.PropTypes.string.isRequired,

};? //?注意這里有分號

static?defaultProps?=?{

? ? ? ? ? ? ? ? ? ? ? ? ? autoPlay:?false,

? ? ? ? ? ? ? ? ? ? ? ? ? ?maxLoops:?10,

};? //?注意這里有分號

2. 實例化階段

該階段主要發(fā)生在組件類被調(diào)用(實例化)的時候。

組件類被實例化的時候,觸發(fā)一系列流程:

1) constructor(props) / getInitialState()

這里是對控件的一些狀態(tài)進行初始化,由于該函數(shù)不同于getDefaultProps,在以后的過程中,會再次調(diào)用,所以可以將控制控件的狀態(tài)的一些變量放在這里初始化,如控件上顯示的文字,可以通過this.state來獲取值,通過this.setState來修改state值。

在ES5里,通過getInitialState對狀態(tài)進行初始化

getInitialState: function() {

? ? ? ? ? ? ? ? ? ? return {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? loopsRemaining: this.props.maxLoops,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?};

},

在ES6里,通過constructor(構(gòu)造器)對狀態(tài)進行初始化

constructor(props){

? ? ? ? super(props);

? ? ? ? this.state = {

? ? ? ? ? ? ? ? ?loopsRemaining: this.props.maxLoops,

? ? ? ? ? ? ? ? ? ? ? ? ? ? };

? ? }

2) componentWillMount()

準備加載組件。

這個調(diào)用時機是在組件創(chuàng)建,并初始化了狀態(tài)之后,在第一次繪制 render() 之前。可以在這里做一些業(yè)務初始化操作,也可以設置組件狀態(tài)。這個函數(shù)在整個生命周期中只被調(diào)用一次。

如果在這個函數(shù)里面調(diào)用setState,本次的render函數(shù)可以看到更新后的state,并且只渲染一次。

3) render()

render是一個組件必須有的方法,形式為一個函數(shù),渲染界面,并返回JSX或其他組件來構(gòu)成DOM,和Android的XML布局、WPF的XAML布局類似,只能返回一個頂級元素

4) componentDidUpdate()

調(diào)用了render方法后,組件加載成功并被成功渲染出來以后所執(zhí)行的hook函數(shù),一般會將網(wǎng)絡請求等加載數(shù)據(jù)的操作,放在這個函數(shù)里進行,來保證不會出現(xiàn)UI上的錯誤

3. 運行(更新)階段

該階段主要發(fā)生在用戶操作之后,或者父組件有更新的時候,此時會根據(jù)用戶的操作行為,進行相應的界面結(jié)構(gòu)調(diào)整。

觸發(fā)的流程如下:

1) componentWillReceiveProps(nextProps)

當組件接收到新的props時,會觸發(fā)該函數(shù)。在該函數(shù)中,通常可以調(diào)用setState()來完成對state的修改

輸入?yún)?shù) nextProps 是即將被設置的屬性,舊的屬性還是可以通過 this.props 來獲取。在這個回調(diào)函數(shù)里面,你可以根據(jù)屬性的變化,通過調(diào)用 this.setState() 來更新你的組件狀態(tài),這里調(diào)用更新狀態(tài)是安全的,并不會觸發(fā)額外的 render() 調(diào)用。如下:

componentWillReceiveProps: function(nextProps) {

? ? ? ? ? ? ? ?this.setState({

? ? ? ? ? ? ? ? ? ? ? ? likesIncreasing: nextProps.likeCount > this.props.likeCount

? ? ? ? ? ? ? ? ? });

}

2) shouldComponentUpdate(nextProps, nextState)

返回布爾值(決定是否需要更新組件)

輸入?yún)?shù) nextProps 和上面的 componentWillReceiveProps 函數(shù)一樣,nextState 表示組件即將更新的狀態(tài)值。這個函數(shù)的返回值決定是否需要更新組件,如果 true 表示需要更新,繼續(xù)走后面的更新流程。否者,則不更新,直接進入等待狀態(tài)。

默認情況下,這個函數(shù)永遠返回 true 用來保證數(shù)據(jù)變化的時候 UI 能夠同步更新。在大型項目中,你可以自己重載這個函數(shù),通過檢查變化前后屬性和狀態(tài),來決定 UI 是否需要更新,能有效提高應用性能。

3) componentWillUpdate(nextProps, nextState)

shouldComponentUpdate返回true或者調(diào)用forceUpdate之后,就會開始準更新組件,并調(diào)用 componentWillUpdate()。

輸入?yún)?shù)與 shouldComponentUpdate 一樣,在這個回調(diào)中,可以做一些在更新界面之前要做的事情。需要特別注意的是,在這個函數(shù)里面,你就不能使用 this.setState 來修改狀態(tài)。這個函數(shù)調(diào)用之后,就會把 nextProps 和 nextState 分別設置到 this.props 和 this.state 中。緊接著這個函數(shù),就會調(diào)用 render() 來更新界面了。

4) render()

再確定需要更新組件時,調(diào)用render,根據(jù)diff算法,渲染界面,生成需要更新的虛擬DOM數(shù)據(jù)。

5) componentDidUpdate()

虛擬DOM同步到DOM中后,執(zhí)行該方法,可以在這個方法中做DOM操作。

除了首次render之后調(diào)用componentDidMount,其它render結(jié)束之后都是調(diào)用componentDidUpdate。

componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以對應起來。區(qū)別在于,前者只有在掛載的時候會被調(diào)用;而后者在以后的每次更新渲染之后都會被調(diào)用。

ps:絕對不要在componentWillUpdate和componentDidUpdate中調(diào)用this.setState方法,否則將導致無限循環(huán)調(diào)用。

4. 銷毀階段

該階段主要發(fā)生組件銷亡的時候,觸發(fā)componentWillUnmount。當組件需要從DOM中移除的時候,通常需要做一些取消事件綁定,移除虛擬DOM中對應的組件數(shù)據(jù)結(jié)構(gòu),銷毀一些無效的定時器等工作,都可以在這個方法中處理。

componentWillUnmount()

當組件要被從界面上移除的時候,就會調(diào)用 componentWillUnmount。

在這個函數(shù)中,可以做一些組件相關的清理工作,例如取消計時器、網(wǎng)絡請求等

三、組件更新的方式(更新階段詳細)

本來是沒有想要要詳細寫這部分內(nèi)容的,不過看到另一篇文章,寫得好好,就也放進來詳細講下,感謝原文作者

參考自:http://www.lxweimin.com/p/4784216b8194里的更新方式部分

更新組件(重新渲染界面)的方式有以下四種

首次渲染Initial Render,即首次加載組件

調(diào)用this.setState,狀態(tài)發(fā)生改變(并不是一次setState會觸發(fā)一次render,React可能會合并操作,再一次性進行render)

父組件發(fā)生更新(一般就是props發(fā)生改變,但是就算props沒有改變或者父子組件之間沒有數(shù)據(jù)交換也會觸發(fā)render)

調(diào)用this.forceUpdate,強制更新

用圖來表示這四種方式如下:


四、總結(jié)

1. 組件生命周期總體流程圖


2. 生命周期的回調(diào)函數(shù)總結(jié)

生命周期 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?調(diào)用次數(shù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 能否使用 setSate()

defaultProps / getDefaultProps ? ? ? ? ? ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (全局調(diào)用一次)

constructor / getInitialState ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?否

componentWillMount ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

render ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?>=1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?否

componentDidMount ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

componentWillReceiveProps ? ? ? ? ? ? ? ? ? ? ? ? ? ? >=0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

shouldComponentUpdate ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?>=0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 否

componentWillUpdate ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?>=0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 否

componentDidUpdate ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? >=0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 否

componentWillUnmount ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 否

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內(nèi)容