React Native 之生命週期

前言

  • 學習本系列內容需要具備一定 HTML 開發基礎,沒有基礎的朋友可以先轉至 HTML快速入門(一) 學習

  • 本人接觸 React Native 時間並不是特別長,所以對其中的內容和性質瞭解可能會有所偏差,在學習中如果有錯會及時修改內容,也歡迎萬能的朋友們批評指出,謝謝

  • 文章第一版出自簡書,如果出現圖片或頁面顯示問題,煩請轉至 簡書 查看 也希望喜歡的朋友可以點贊,謝謝

React Native 組件執行順序介紹


  • 所有的程序都有生命週期,這是開發人員關注的點,比如iOS中有一個 ViewDidLoad 來初始化,在React Native中又是在哪裏?這邊從文檔中截取的一張圖並註釋了下,很好地描述了React Native組件的執行順序

React Native執行順序.png
- 從圖中可以看出,在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>
                );
            }
        });
    

    效果:
    getDefaultProps和getInitialState使用.gif

    • 注:一旦調用了 this.setState方法,組件一定會調用render方法,對組件進行再次渲染,不過,React框架會根據DOM的狀態自動判斷是否需要真正渲染
  • 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.state探究.gif

    • 當用戶點擊組件,導致狀態變化,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);
            }
        });
    

    效果:
    打印結果.png

    • 可以看出,組件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的基礎,事實也證明這兩個假設是合理而精確的,保證了整體界面構建的性能
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章