09 React Native組件生命周期

(申明: 此系列教程,轉(zhuǎn)載旋之華微信公眾號(hào),如有侵權(quán) . 通知?jiǎng)h除~)

(大家可以添加他的微信公眾號(hào)了解更多內(nèi)容.)

image.png

對(duì)于習(xí)慣了iOS開發(fā)的同學(xué),可能會(huì)對(duì)React Native中組件的生命周期很困惑。在iOS中有一個(gè)ViewDidLoad來初始化,那么在RN中,又是在哪里呢?

一、看圖分析

在下圖中描述了React Native中組件的生命周期,我們可以根據(jù)其中的執(zhí)行順序在對(duì)應(yīng)的函數(shù)中做對(duì)應(yīng)的操作。

image

React Native組件的生命周期大致上可以劃分為

實(shí)例化階段

、

存在階段

銷毀階段

,其中最常用的為

實(shí)例化階段

,該階段就是組件的構(gòu)建、展示時(shí)期,需要我們根據(jù)幾個(gè)函數(shù)的調(diào)用過程,控制好組件的展示和邏輯的處理。

二、實(shí)例化階段函數(shù)功能分析

getDefaultProps

該函數(shù)用于初始化一些默認(rèn)的屬性,通常會(huì)將固定的內(nèi)容放在這個(gè)函數(shù) 中進(jìn)行初始化和賦值;

    在組件中,可以利用

this.props

獲取在這里初始化它的屬性,由于組件初始化后,再次使用該組件不會(huì)調(diào)用getDefaultProps函數(shù),所以組件自己不可以自己修改props(即:props可認(rèn)為是只讀的),只可由其他組件調(diào)用它時(shí)在外部修改。

getInitialState

該函數(shù)是用于對(duì)組件的一些狀態(tài)進(jìn)行初始化;

   由于該函數(shù)不同于getDefaultProps,在以后的過程中,會(huì)再次調(diào)用,所以可以將控制控件的狀態(tài)的一些變量放在這里初始化,如控件上顯示的文字,可以通過

this.state

來獲取值,通過

this.setState

來修改state值, 比如:

<pre style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;">

this.setState({
activePage: activePage,
currentX: contentOffSetX
});

</pre>

注意:

一旦調(diào)用了this.setState方法,組件一定會(huì)調(diào)用render方法,對(duì)組件進(jìn)行再次的渲染,不過,如果React框架會(huì)自動(dòng)根據(jù)DOM的狀態(tài)來判斷是否需要真正的渲染。

componentWillMount

相當(dāng)于OC中的ViewWillAppear方法,在

組件將要被加載在視圖上之前調(diào)用,功能相對(duì)較少。

render

render是一個(gè)組件中必須有的方法,本質(zhì)上是一個(gè)函數(shù),并返回JSX或其他組件來構(gòu)成DOM,和Android的XML布局類似,注意:

只能返回一個(gè)頂級(jí)元素

;

   此外,在render函數(shù)中,只可通過

this.state

this.props

來訪問在之前函數(shù)中初始化的數(shù)據(jù)值 。

componentDidMount

在調(diào)用了render方法后,組件加載成功并被成功渲染出來以后,所要執(zhí)行的后續(xù)操作,一般會(huì)在這個(gè)函數(shù)中處理網(wǎng)絡(luò)請(qǐng)求等加載數(shù)據(jù)的操作;

   因?yàn)閁I已經(jīng)成功被渲染出來, 所以放在這個(gè)函數(shù)里進(jìn)行請(qǐng)求操作,不會(huì)出現(xiàn)UI上的錯(cuò)誤。

  下圖是利用了fetch API來異步請(qǐng)求Web API來加載數(shù)據(jù):
image

三、存在期階段函數(shù)功能分析

componentWillReceiveProps

指父元素對(duì)組件的props或state進(jìn)行了修改

shouldComponentUpdate

一般用于優(yōu)化,可以返回false或true來控制是否進(jìn)行渲染

componentWillUpdate

組件刷新前調(diào)用,類似componentWillMount

componentDidUpdate

更新后的hook

四、銷毀期階段函數(shù)功能分析

   用于清理一些無用的內(nèi)容,如:點(diǎn)擊事件Listener,只有一個(gè)過程:

componentWillUnmount

****五、常用知識(shí)點(diǎn)分析****

****5.1 this.state ****

    開發(fā)中組件免不了要與用戶互動(dòng),React 的一大創(chuàng)新,就是將組件看成是一個(gè)狀態(tài)機(jī),一開始有一個(gè)初始狀態(tài),然后用戶互動(dòng),導(dǎo)致狀態(tài)變化,從而觸發(fā)重新渲染 UI。

   舉個(gè)例子:
image
   當(dāng)用戶點(diǎn)擊組件,導(dǎo)致狀態(tài)變化, **this.setState**  方法就修改狀態(tài)值,每次修改以后,自動(dòng)調(diào)用  **this.render** 方法,再次渲染組件。

  可以把組件看成一個(gè)“狀態(tài)機(jī)”. 根據(jù)不同的status有不同的UI展示。只要使用setState改變狀態(tài)值,根據(jù)diff算法算出來有差以后,就會(huì)執(zhí)行ReactDom的render方法,重新渲染頁(yè)面。

注意:由于 this.props 和 this.state 都用于描述組件的特性,可能會(huì)產(chǎn)生混淆。一個(gè)簡(jiǎn)單的區(qū)分方法是,this.props 表示那些一旦定義,就不再改變的特性,而 this.state 是會(huì)隨著用戶互動(dòng)而產(chǎn)生變化的特性。

5.2 獲取真實(shí)的DOM節(jié)點(diǎn)

在React Native中,組件并不是真實(shí)的 DOM 節(jié)點(diǎn),而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),叫做虛擬 DOM (virtual DOM)。

  只有當(dāng)它插入文檔以后,才會(huì)變成真實(shí)的 DOM 。

  根據(jù) React 的設(shè)計(jì),所有的 DOM 變動(dòng),都先在虛擬 DOM 上發(fā)生,然后再將實(shí)際發(fā)生變動(dòng)的部分,反映在真實(shí) DOM上,這種算法叫做 DOM diff,它可以極大提高網(wǎng)頁(yè)的性能表現(xiàn)。

 但是,有時(shí)需要從組件獲取真實(shí) DOM 的節(jié)點(diǎn),這時(shí)就要用到

ref

屬性;

 下圖通過一個(gè)案例來演示:
image

運(yùn)行結(jié)果如下:

image
   上面代碼中,組件 View 的子節(jié)點(diǎn)有一個(gè)文本輸入框,用于獲取用戶的輸入。這時(shí)就必須獲取真實(shí)的 DOM 節(jié)點(diǎn),虛擬 DOM 是拿不到用戶輸入的。為了做到這一點(diǎn),文本輸入框必須有一個(gè) ref屬性,然后 this.refs.[refName] 就會(huì)返回這個(gè)真實(shí)的 DOM 節(jié)點(diǎn)。

  需要注意的是,由于 

this.refs.[refName]

屬性獲取的是真實(shí) DOM ,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個(gè)屬性,否則會(huì)報(bào)錯(cuò)。上面代碼中,通過為組件指定 Click 事件的回調(diào)函數(shù),確保了只有等到真實(shí) DOM 發(fā)生 Click 事件之后,才會(huì)讀取

this.refs.[refName]

屬性。

六、案例實(shí)操

案例主要技術(shù)點(diǎn):

充分利用了RN生命周期的鉤子函數(shù),實(shí)現(xiàn)界面刷新。

1.1 利用控件的索引index計(jì)算出控件所在的行號(hào)和列號(hào)

1.2 利用列號(hào)計(jì)算控件的x值

1.3 利用行號(hào)計(jì)算控件的y值

案例思路截圖:

image

案例核心代碼:

image
image
image

****案例運(yùn)行效果截圖:****

image

八、總結(jié)

React Native組件的生命周期,經(jīng)歷了Mount->Update->Unmount這三個(gè)大的過程,即從創(chuàng)建到銷毀的過程,結(jié)合OC中的開發(fā)經(jīng)驗(yàn),我們?cè)谝陨系幕A(chǔ)上應(yīng)該可以快速的上手React Native的開發(fā)。

九、引用

9.1 什么是DOM Diff算法

   Web界面由DOM樹來構(gòu)成,當(dāng)其中某一部分發(fā)生變化時(shí),其實(shí)就是對(duì)應(yīng)的某個(gè)DOM節(jié)點(diǎn)發(fā)生了變化。在React中,構(gòu)建UI界面的思路是由當(dāng)前狀態(tài)決定界面。前后兩個(gè)狀態(tài)就對(duì)應(yīng)兩套界面,然后由React來比較兩個(gè)界面的區(qū)別,這就需要對(duì)DOM樹進(jìn)行Diff算法分析。

   即給定任意兩棵樹,找到最少的轉(zhuǎn)換步驟。但是標(biāo)準(zhǔn)的的Diff算法復(fù)雜度需要O(n^3),這顯然無法滿足性能要求。要達(dá)到每次界面都可以整體刷新界面的目的,勢(shì)必需要對(duì)算法進(jìn)行優(yōu)化。這看上去非常有難度,然而Facebook工程師卻做到了,他們結(jié)合Web界面的特點(diǎn)做出了兩個(gè)簡(jiǎn)單的假設(shè),使得Diff算法復(fù)雜度直接降低到O(n)
  1. 兩個(gè)相同組件產(chǎn)生類似的DOM結(jié)構(gòu),不同的組件產(chǎn)生不同的DOM結(jié)構(gòu);

  2. 對(duì)于同一層次的一組子節(jié)點(diǎn),它們可以通過唯一的id進(jìn)行區(qū)分。

    算法上的優(yōu)化是React整個(gè)界面Render的基礎(chǔ),事實(shí)也證明這兩個(gè)假設(shè)是合理而精確的,保證了整體界面構(gòu)建的性能。
    

9.2 ES5和ES6的差異化?

   es5,es6 都是對(duì) ecmascript規(guī)范的補(bǔ)充,es5已經(jīng)大規(guī)模使用了,es6目前可能在個(gè)別平臺(tái)存在瀏覽器兼容性問題; 其中箭頭函數(shù)()=>()是ES6獨(dú)有的。

區(qū)別1:創(chuàng)建組件

   組件是一個(gè)自定義的js對(duì)象,在es5中使用React.createClass();在es6中必須繼承React.component,然后進(jìn)行創(chuàng)建。

ES5的寫法:

image

ES6的寫法:

image

區(qū)別2:組件的屬性props

在ES6中,其為屬性:defaultProps(可以標(biāo)識(shí)static定義在class內(nèi),也可以定義在class外),而

在ES5中,其為方法:getDefaultProps: function(){return {name:value}};

ES5:

image

ES6:

image

區(qū)別3:

組件的狀態(tài)state

ES5:

image

ES6:

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容