1. 程式人生 > >React-Native開發三 React Native元件生命週期

React-Native開發三 React Native元件生命週期

1 前言

大家都知道React Native其實是由很多元件構成,開發RN介面的過程就是合理的組織各個元件的過程,在這其中需要不斷的拆分和優化元件。因此理解RN元件的生命週期很重要,這樣我們才能合理的在元件中進行我們的事務。

2 React Native元件生命週期

RN元件的生命週期分為四個階段 分別是:建立階段 例項化階段 執行(更新)階段 銷燬階段
整體流程圖如下(借用別人的圖)
這裡寫圖片描述
下面分別介紹各個元件的生命週期

3 建立階段

建立階段主要發生在建立元件類的時候,在這個階段中主要是初始化元件的屬性型別和預設屬性,例如元件的props的初始化,和一些變數的初始化
一般在這個階段中主要做的工作如下:
初始化props,在ES6中定義靜態的方法來初始化props

    //定義預設屬性
    static defaultProps = {
        autoPlay:false,
        maxLoops:10,
    };

    //定義proTypes
    static propTypes = {
      autoPlay:PropTypes.bool.isRequired,

      maxLoops:PropTypes.number.isRequired,
    };

注意:初始化一般只執行一次,這一點與java中類的初始化類似

4 例項化階段

例項化階段主要從建構函式開始,主要進行元件的例項化過程,包括載入,渲染等
1 constructor(props)


這裡是對控制元件的一些狀態進行初始化,由於該函式不同於defaultProps,在以後的過程中,會再次呼叫,所以可以將控制控制元件的狀態的一些變數放在這裡初始化。
主要用於state的定義和初始化。

在ES6裡,通過constructor(構造器)對狀態進行初始化
    //元件例項化時呼叫 可呼叫多次
    constructor(props){
        super(props);
        console.log("constructor");
        this.state = {
            loopsRemaining:this.props.maxLoops,
        }
;
}

2 componentWillMount()
該函式表示元件將要被載入的回撥,該函式的呼叫在元件初始化了狀態即呼叫建構函式之後,並且在render()之前。
主要用於進行一些業務的初始化。
函式只調用依次,如果呼叫setState(),其結果可以被render()看到

    //例項化 準備載入元件
    componentWillMount() {
        console.log('componentWillMount');
    }

3 render()
render是一個元件必須有的方法,形式為一個函式,渲染介面,並返回JSX或其他元件來構成DOM,和Android的XML佈局、WPF的XAML佈局類似,只能返回一個頂級元素。

render() {
        console.log("render()");
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    Welcome to React Native!
                </Text>
                <Text style={styles.instructions}>
                    To get started, edit App.js
                </Text>
                <Text style={styles.instructions}>
                    {instructions}
                </Text>
                <Greeting name='React 1'/>
                <Greeting name='React 2'/>
                <Greeting name='React 3'/>

                <TouchableHighlight onPress={this._onPressButton}>
                    <Text>Button</Text>
                </TouchableHighlight>
            </View>
        );
    }

render主要用於渲染介面,因此這個函式和UI相關,一般會用JSX語言來插入各種元件,以實現整個頁面的構建

4 componentDidMount()
該函式在render()之後,表示元件已經被載入完成。這個函式呼叫時表示其虛擬 DOM 已經構建完成,你可以在這個函式開始獲取其中的元素或者子元件了。需要注意的是,RN 框架是先呼叫子元件的 componentDidMount(),然後呼叫父元件的函式。從這個函式開始,就可以和 JS 其他框架互動了,例如設定計時 setTimeout 或者 setInterval,或者發起網路請求。這個函式也是隻被呼叫一次。這個函式之後,就進入了穩定執行狀態,等待事件觸發。

    componentDidMount() {
        console.log('componentDidMount');
    }

到這裡整個例項化階段就算完成了,我們來看各個函式的呼叫過程,執行效果如下:
這裡寫圖片描述

注意各個函式呼叫順序。
接下來就是執行階段了,執行階段會等待事件的出發,一旦出發事件,將會有執行階段的流程。

5 執行階段

執行階段在例項化階段之後,執行階段主要發生在使用者操作之後,或者父元件有更新時,此時子元件需要進行相應的事件出發。
觸發流程如下:
1 componentWillReceiveProps(nextProps)
當元件接收到新的props時,會觸發該函式。在該函式中,通常可以呼叫setState()來完成對state的修改。
注意:屬性一般是父元件傳遞給子元件的,

    //在元件渲染完成之後,當reactNative元件接受到新的props時,這個函式將被呼叫,這個函式接受一個object引數,object裡時新的props。
    componentWillReceiveProps(nextProps) {
        this.setState({loopsRemaining:nextProps.maxLoops});
        console.log('componentWillReceiveProps' + nextProps.value);
    }

輸入引數 nextProps 是即將被設定的屬性,舊的屬性還是可以通過 this.props 來獲取。在這個回撥函式裡面,你可以根據屬性的變化,通過呼叫 this.setState() 來更新你的元件狀態,這裡呼叫更新狀態是安全的,並不會觸發額外的 render() 呼叫。如下

2 shouldComponentUpdate(nextProps, nextState)
表示元件是否需要更新,該函式返回布林值(決定是否需要更新元件),當不需要更新時可以複寫該函式返回false

    //返回布林值(決定是否需要更新元件)
    shouldComponentUpdate(nextProps,nextState){
        console.log("shouldComponentUpdate");
        return true;
    }

輸入引數 nextProps 和上面的 componentWillReceiveProps 函式一樣,nextState 表示元件即將更新的狀態值。這個函式的返回值決定是否需要更新元件,如果 true 表示需要更新,繼續走後面的更新流程。否者,則不更新,直接進入等待狀態。
預設情況下,這個函式永遠返回 true 用來保證資料變化的時候 UI 能夠同步更新。在大型專案中,你可以自己過載這個函式,通過檢查變化前後屬性和狀態,來決定 UI 是否需要更新,能有效提高應用效能。

3 componentWillUpdate(nextProps, nextState)
當元件需要更新時,就會回撥該函式,然後就會呼叫render()更新元件

    //元件將要更新
    componentWillUpdate(nextProps, nextState){
        console.log("componentWillUpdate");
    }

輸入引數與 shouldComponentUpdate 一樣,在這個回撥中,可以做一些在更新介面之前要做的事情。需要特別注意的是,在這個函式裡面,你就不能使用 this.setState 來修改狀態。這個函式呼叫之後,就會把 nextProps 和 nextState 分別設定到 this.props 和 this.state 中。緊接著這個函式,就會呼叫 render() 來更新介面了。

4 render()
再確定需要更新元件時,呼叫render,根據diff演算法,渲染介面,生成需要更新的虛擬DOM資料。

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

    //元件已經更新
    componentDidUpdate() {
        console.log("componentDidUpdate");
    }

除了首次render之後呼叫componentDidMount,其它render結束之後都是呼叫componentDidUpdate。

componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以對應起來。區別在於,前者只有在掛載的時候會被呼叫;而後者在以後的每次更新渲染之後都會被呼叫。

注意:絕對不要在componentWillUpdate和componentDidUpdate中呼叫this.setState方法,否則將導致死迴圈

整個執行階段結果如下:

6 銷燬階段

當元件不需要存在時,就會進行元件的銷燬階段,該階段只有一個方法componentWillUnmount()
1 componentWillUnmount()
該方法中做一些元件清除的工作,比如銷燬定時器等,取消網路請求等

    //銷燬階段 元件將要銷燬
    componentWillUnmount(){
        console.log("componentWillUnmount");
    }

7 RN 元件生命週期總結

根據前面的RN生命週期介紹,下面總結一下各個生命週期的呼叫次數和能否使用setState()來改變狀態
這裡寫圖片描述

總結:RN元件的生命週期還是比較清晰的,與Activity最大的區別就是將例項化階段和後續的更新階段分開了。

參考:https://www.jianshu.com/p/379aecebb1dc