react生命週期學習



組件的生命週期分爲三個部分:(1)實例化;(2)存在期;(3)銷燬&清理期。具體週期如下圖所示:


1.1 實例化

創建在代碼加載過程中至關重要,重要之處體現什麼地方呢,這裏粗略的簡述幾點,(1)實例化是首次加載js展示給用戶最直觀的內容,效率的高低直接決定體驗的好壞;(2)實例化過程是對數據進行說明和描述的過程。(3)實例化過程完成了虛擬DOM和真實DOM的生成。下面看下示例來展示當前流程:

var React = require("react");
var ReactDOM = require("react-dom");

var List = React.createClass({
    //1.創建階段
    getDefaultProps:function() {
        console.log("getDefaultProps");
        return {};
    },

    //2.實例化階段
    getInitialState:function() {
        console.log("getInitialState");
        return {};
    },

    //render之前調用,業務邏輯都應該放在這裏,如對state的操作等
    componentWillMount:function() {
        console.log("componentWillMount");
    },

    //渲染並返回一個虛擬DOM
    render:function() {
        console.log("render");
        return(
            <div> hello <strong> {this.props.name} </strong></div>
            );
    },

    //該方法發生在render方法之後。在該方法中,ReactJS會使用render生成返回的虛擬DOM對象來創建真實的DOM結構
    componentDidMount:function() {
        console.log("componentDidMount");
    },
});

ReactDOM.render(<List name="ReactJS">children</List>, document.body);

輸出結果爲:

getDefaultProps
getInitialState
componentWillMount
render
componentDidMount

上面經歷的實例化過程可細分成兩個階段:創建階段和實例化階段

1.1.1創建階段

該階段主要發生在創建組件類的時候,即調用React.createClass的時候。這個階段只會觸發一個getDefaultProps方法,該方法返回一個對象,並且緩存下來。然後與父組件指定的props對象合併,最後賦值給this.props作爲該組件的默認屬性。對於那些沒有被父輩組件指定的props屬性的新建實例來說,這個方法返回的對象可用於爲實例設置默認的props值。

props屬性又是什麼呢,它是一個對象,是組件用來接收外面傳來的參數的,組件內部是不允許修改自己的props屬性的,只能通過父組件來修改。在getDefaultProps方法中,是可以設定props默認值的。

1.1.2實例化階段

該階段主要發生在實例化組件類的時候,也就是該組件類被調用的時候:

ReactDOM.render(<NewView name="ReactJS">children</NewView>, document.body);

調用順序在demo結果中頁

  • getInitialState 初始化組件的state的值,其返回值會賦值給組件的this.state屬性。對於組件的每個實例來說,這個方法的調用次數有且只有一次。與getDefaultProps方法不同的是,每次實例創建時該方法都會被調用一次。
  • componentWillMount 此方法會在完成首次渲染之前被調用。這也是在render方法調用前可以修改組件state的最後一次機會。
  • render 生成頁面需要的虛擬DOM結構,用來表示組件的輸出。render方法需要滿足:(1)只能通過this.props和this.state訪問數據;(2)可以返回null、false或者任何React組件;(3)只能出現一個頂級組件;(4)必需純淨,意味着不能改變組件的狀態或者修改DOM的輸出。
  • componentDidMount 該方法發生在render方法成功調用並且真實的DOM已經被渲染之後,在該函數內部可以通過this.getDOMNode()來獲取當前組件的節點。然後就可以像Web開發中的那樣操作裏面的DOM元素了。

上面提到了兩個比較生分的術語——state和虛擬DOM

  • state:是組建的屬性,主要用來存儲組件自身需要的數據。它是可以改變的,它的每次改變都會引起組件的更新,這也是ReactJS中的關鍵點之一。每次數據的更新都是通過修改state屬性的值,然後ReactJS內部會監聽state屬性的變化,一旦發生變化,就會主動出發組件的render方法來更新DOM結構。
  • 虛擬DOM:它是ReactJS中提出的一個概念,是將真實的DOM結構映射成一個JSON數據結構,在有數據更改的時候更新真實的DOM,不需修改的時候不更新真實的DOM。

1.2 存在期

由1.1可知,此時組件已經渲染好並且用戶可以與它進行交互,通常是通過一次鼠標點擊、手指點按或者鍵盤事件來觸發一個事件處理器。隨着用戶改變了組件或者整個應用的state,便會有新的state流入組件結構樹。代碼如下所示:

var React = require("react");
var ReactDOM = require("react-dom");

var NewView = React.createClass({
    //1.創建階段
    getDefaultProps:function() {
        console.log("getDefaultProps");
        return {};
    },

    //2.實例化階段
    getInitialState:function() {
        console.log("getInitialState");
        return {
            num:1
        };
    },

    //render之前調用,業務邏輯都應該放在這裏,如對state的操作等
    componentWillMount:function() {
        console.log("componentWillMount");
    },

    //渲染並返回一個虛擬DOM
    render:function() {
        console.log("render");
        return(
            <div> hello <strong> {this.props.name} </strong>
                <button onClick={this.handleAddNumber}> hello <strong> {this.state.num} </strong></button>
            </div>
            );
    },

    //該方法發生在render方法之後。在該方法中,ReactJS會使用render生成返回的虛擬DOM對象來創建真實的DOM結構
    componentDidMount:function() {
        console.log("componentDidMount");
    },

    //3.更新階段
    componentWillReceiveProps:function() {
        console.log("componentWillReceiveProps");
    },

    //是否需要更新
    shouldComponentUpdate:function() {
        console.log("shouldComponentUpdate");
        return true;
    },

    //將要更新
    componentWillUpdate:function() {
        console.log("componentWillUpdate");
    },

    //更新完畢
    componentDidUpdate:function() {
        console.log("componentDidUpdate");
    },

    //4.銷燬階段
    componentWillUnmount:function() {
        console.log("componentWillUnmount");
    },

    // 處理點擊事件
    handleAddNumber:function() {
        console.log("add num");
        this.setState({num:this.state.num+1});
        this.setProps({name:"newName"});
    }
});
ReactDOM.render(<NewView name="ReactJS"></NewView>, document.body);

該段代碼的目的是,經歷第一階段實例化階段,然後提供button按鈕,改變state狀態,也是調用代碼中的handleAddNumber:function()方法,實現第二階段存在期的更新,該階段在state狀態f發生改變,組件逐漸受到影響。

輸出結果爲(不包含):

add num
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
  • componentWillReceiveProps 在任意時刻,組件的props都可以通過父輩組件來更改。當組件接收到新的props(這裏不同於state)時,會觸發該函數,我們同時也獲得更改props對象及更新state的機會。
  • shouldComponentUpdate 該方法用來攔截新的props和state,然後開發者可以根據自己設定邏輯,做出要不要更新render的決定,讓它更快。
  • componentWillUpdate 與componentWillMount方法類似,組件上會接收到新的props或者state渲染之前,調用該方法。但是不可以在該方法中更新state和props。
  • render 生成頁面需要的虛擬DOM結構,並返回該結構
  • componentDidUpdate 與componentDidMount類似,更新已經渲染好的DOM。

1.3生命週期之銷燬&清理

每當react使用完一個組件,這個組件就必須從DOM中卸載隨後被銷燬。此時,僅有的一個鉤子函數會做出響應,完成所有的清理與銷燬工作,這很必要。

componentWillUnmount

最後,隨着一個組件從它的層級結構中移除,這個組件的生命也就走到了盡頭。該方法會在組件被移出之前調被調用。在componentDidMount方法中添加的所有任務都需要在該方法中撤銷,比如說創建的定時器或者添加的事件監聽等。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章