前言
-
學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 HTML快速入門(一) 學習
-
本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質了解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝
-
文章第一版出自簡書,如果出現圖片或頁面顯示問題,煩請轉至 簡書 查看 也希望喜歡的朋友可以點贊,謝謝
React Native 組件執行順序介紹
- 所有的程序都有生命周期,這是開發人員關注的點,比如iOS中有一個
ViewDidLoad
來初始化,在React Native中又是在哪里?這邊從文檔中截取的一張圖並注釋了下,很好地描述了React Native組件的執行順序
- 從圖中可以看出,在React Native中,組件的生命周期大致可以分為3個階段(
實例化階段、存在階段、銷毀階段
),其中最常接觸的為實例化階段,這個階段負責組件的構建和展示的時間,需要我們根據幾個函數的調用過程,控制好組件的展示和邏輯處理
實例化階段函數功能分析
-
getDefaultProps:該函數用於初始化一些默認屬性,通常會將固定的內容放在這個函數中進行初始化和賦值
- 在組件中,我們可以利用
this.props
獲取在這里初始化它的屬性,由於組件初始化后,再辭使用該組件不會調用getDefaultProps
函數,所以組件自己不可以修改props,只可由其他組件調用它時再外部進行修改
- 在組件中,我們可以利用
-
getInitialState:該函數用於對組件一些狀態進行初始化
- 該函數不同於getDefaultProps,在以后的過程中,會再次調用,所以可以將控制控件狀態的一些變量放在這里初始化,比如控件上顯示的文字,可以通過this.state來獲取值,通過
this.setState
來修改state值
var SMZQ = React.createClass({ // 用於設置一些值固定不變或上下界面值傳遞 getDefaultProps(){ return{ number1: 1, number2: 2 } }, // 用於設置一些可變或者用來刷新界面 getInitialState(){ return{ sum:0 } }, render() { return ( <View style={styles.container}> <Text>number1:{this.props.number1}</Text> <Text>number2:{this.props.number2}</Text> <Text>sum:{this.state.sum}</Text> <TouchableOpacity onPress={() => {this.setState({sum: this.props.number1 + this.props.number2})}} > <Text>計算和</Text> </TouchableOpacity> <TouchableOpacity onPress={() => {this.setState({sum: this.state.sum + 1})}} > <Text>和的基礎上+1</Text> </TouchableOpacity> </View> ); } });
效果:
- 注:一旦調用了
this.setState
方法,組件一定會調用render方法,對組件進行再次渲染,不過,React框架會根據DOM的狀態自動判斷是否需要真正渲染
- 該函數不同於getDefaultProps,在以后的過程中,會再次調用,所以可以將控制控件狀態的一些變量放在這里初始化,比如控件上顯示的文字,可以通過this.state來獲取值,通過
-
componentWillMount:相當於OC中的
ViewWillAppear
方法,在組件簡要被加載到視圖之前調用,沒有太多的功能 -
render:它是每個組件必需具備的方法,本質上是個函數,並且返回JSX或者其他組件來構成DOM,和Android的XML布局類似
- 在該函數中,只能通過this.state和this.props來訪問之前在函數中初始化的數值
- 注:只能返回一個頂級元素
-
componentDidMount:在調用了render方法,組件加載成功並被成功渲染出來之后,所要執行的后續操作,一般都會在這個函數中進行,比如經常要面對的網絡請求等加載數據操作
- 因為UI已經成功渲染,而且這里面是異步的,索引放在這個函數進行數據的請求等復雜的操作,不會出現UI錯誤
存在階段函數功能分析
- componentWillReceiveProps:指父元素對組件的props或state進行了修改
- shouldComponentUpadate:一般用於優化,可以返回false或true來控制是否進行渲染
- componentWillUpdate:組件刷新前調用,類似componentWillMount
- componentDidUpdate:更新后的hook
銷毀階段函數功能分析
- 用於清理一些無用的內容,如:點擊事件Listener,只有一個過程:componentWillUnmount
常用知識點分析
-
this.state:開發中,組件肯定要與用戶互動,React的一大創新就是將組件看成一個狀態機,一開始有一個初始狀態,然后用戶互動,導致狀態變化,從而觸發重新渲染UI,舉個例子
var SMZQ = React.createClass({ // 用於設置一些可變或者用來刷新界面 getInitialState(){ return{ isPositive: true, content:'5是不是負數' } }, render() { return ( <View style={styles.container}> <TouchableOpacity onPress={() => {this.dealWithState(this.state.isPositive, 5)}} > <Text>{this.state.content}</Text> </TouchableOpacity> </View> ); }, dealWithState: function (data:Boolean, num:int) { var isPositive, content; if (num > 0){ isPositive = false; content = '值不是負數'; }else { isPositive = true; content = '值是負數'; } this.setState({ isPositive: isPositive, content: content }); } });
效果:
- 當用戶點擊組件,導致狀態變化,this.setState方法就修改狀態值,每次修改以后,會自動調用this.render方法,再次渲染組件
- 可以把組件看成一個狀態機,根據不同的status有不同的UI展示,只要使用setState改變狀態值,根據diff算法算出有差值后,就會執行ReactDom的render方法,重新渲染頁面
- 注:由於this.props和this.state都用於描述組件的特性,可能會產生混淆,一個簡單的區分方法就是 —— this.props表示那些一旦定義,就不再更改的特性,而this.state是會隨着用戶互動而產生改變的特性
-
獲取真實的DOM節點
- 在React Native中,組件並不是真實的DOM節點,而是存在於內存中的一種數據結構 ,叫虛擬DOM
- 只有當它插入文檔后,才會變成真實的DOM
- 根據React的設計,所有DOM變動,都先在虛擬DOM上發生,然后再將實際發生變動的部分,反應在真實DOM上,這種算法叫做DOM diff,它可以極大提高網頁的性能表現
- 有時需要從組件獲取真實DOM節點,這時就需要用到ref屬性,可以看下面的示例加深理解
var SMZQ = React.createClass({ render() { return ( <View ref="mainView" style={styles.container}> <TouchableOpacity onPress={() => {this.dealWithState()}} > <Text>值</Text> </TouchableOpacity> <TextInput ref="mytextInput"></TextInput> </View> ); }, dealWithState: function () { // 讓輸入框獲得焦點 this.refs.mytextInput.focus(); // 查看內容屬性 console.log(this.refs.mainView); } });
效果:
- 可以看出,組件View的子節點有一個文本輸入框,用於獲取用戶的輸入,這時就必須獲取真實的DOM節點,虛擬DOM是拿不到用戶輸入的,為了做到這一點,文本輸入框必須有一個ref屬性,然后this.refs.refName就會返回這個真實的DOM節點
- 需要注意的是,由於this.refs.refName屬性獲取的是真實DOM,所有必須等到虛擬DOM插入文檔后,才能使用這個屬性,否則會報錯。上面代碼中,通過組件指定Click事件的回調函數,確保只有等到真實DOM發生Click事件之后,才會讀取this.refs.refName屬性
補充
- 什么是DOM Diff算法(下面內容是搜索的內容)
- Web界面由DOM樹來構成,當其中某一部分發生變化時,其實就是對應的某個DOM節點發生了變化。在React中,構建UI界面的思路是由當前狀態決定界面。前后兩個狀態就對應兩套界面,然后由React來比較兩個界面的區別,這就需要對DOM樹進行Diff算法分析
- 即給定任意兩棵樹,找到最少的轉換步驟。但是標准的的Diff算法復雜度需要O(n^3),這顯然無法滿足性能要求。要達到每次界面都可以整體刷新界面的目的,勢必需要對算法進行優化。這看上去非常有難度,然而Facebook工程師卻做到了,他們結合Web界面的特點做出了兩個簡單的假設,使得Diff算法復雜度直接降低到O(n)
- 兩個相同組件產生類似的DOM結構,不同的組件產生不同的DOM結構
- 對於同一層次的一組子節點,它們可以通過唯一的id進行區分
-算法上的優化是React整個界面Render的基礎,事實也證明這兩個假設是合理而精確的,保證了整體界面構建的性能