React學習筆記(三)-- 組件的生命周期

摘要

React中的組件類似于狀態(tài)機,每個組件都被設(shè)計成為在其生命周期過程中輸出穩(wěn)定、語義化的標簽。React組件的生命周期大致可以分為:創(chuàng)建時,存在期及銷毀時。為了更好的控制每個生命周期環(huán)節(jié),React提供了對應(yīng)的鉤子函數(shù)。

簡介

我們知道React里面的組件其實就是一個簡單的函數(shù),這些函數(shù)完成了對數(shù)據(jù)和方法的封裝,來幫助我們分離應(yīng)用中的關(guān)注點,最終實現(xiàn)對頁面的渲染。在組件的生命周期中,由于用戶與應(yīng)用間的交互,組件的props和states也會隨之改變,相應(yīng)的DOM也會發(fā)生變化。

React將組件的生命周期大概分為三個階段:創(chuàng)建時,存在期及銷毀時。每個階段都對應(yīng)著特定的鉤子函數(shù)做出響應(yīng),接下來詳細看一下這三個階段。

創(chuàng)建時

一個實例初始化時調(diào)用的方法與其他各個后續(xù)實例創(chuàng)建時調(diào)用的方法略有不同。當我們首次初始化一個組件類的時候,會依次調(diào)用如下方法:

  • getDefaultProps
  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

對于該組件類的所有后續(xù)應(yīng)用,對比組件初始化過程,除了getDefaultProps方法,其他方法均會被調(diào)用:

  • getInitialState
  • componentWillMount
  • render
  • componentDidMount

存在期

初始化之后的組件會隨著應(yīng)用狀態(tài)的改變,逐漸受到影響,會有如下方法依次執(zhí)行:

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

銷毀時

最后,該組件使用完成后,componentWillUnmount方法將會被調(diào)用。

三個階段對應(yīng)的函數(shù)調(diào)用如上所述,接下來看一下每個方法的具體含義及作用。

組件的常見屬性及方法

getDefaultProps

在組件類創(chuàng)建的時候調(diào)用一次,然后返回值被緩存下來。如果父組件沒有指定 props 中的某個鍵,則此處返回的對象中的相應(yīng)屬性將會合并到 this.props (使用 in 檢測屬性)。該方法在任何實例創(chuàng)建之前調(diào)用,因此不能依賴于 this.props。另外,getDefaultProps() 返回的任何復(fù)雜對象將會在實例間共享,而不是每個實例擁有一份拷貝。

getInitialState

在每次組件掛載前均會被調(diào)用,返回值會作為this.state的初始值。在該方法內(nèi)部允許調(diào)用this.props

render

對于每一個組件來說,render()方法是必須的。render方法會創(chuàng)建一個虛擬DOM對象(比如<div/> 或者 React.DOM.div()),作為當前組件的一個輸出,同時React要求render方法滿足以下幾點要求:

  • 只能出現(xiàn)一個頂級組件;
  • 通過this.propsthis.state訪問數(shù)據(jù);
  • 可以返回null,false或者任何React組件(當返回 null 或者 false 的時候,this.getDOMNode() 將返回 null。);
  • 盡量保證render函數(shù)不修改組件 state,不修改DOM的輸出,也不和瀏覽器交互,每次調(diào)用都返回相同結(jié)果。

說明:如果需要和瀏覽器交互,在 componentDidMount() 中或者其它生命周期方法中做這件事。保持render() 純粹,可以使服務(wù)器端渲染更加切實可行,也使組件更容易被理解。

propTypes

propTypes 對象允許驗證傳入到組件的 props(規(guī)定了組件props的類別與必須狀態(tài))。

var Test = React.createClass({ 
    propTypes: {
        requiredFunc: React.PropTypes.func.isRequired, // 函數(shù)且必須
        requiredAny: React.PropTypes.any.isRequired, // 可以是任何格式且必須
        bool: React.PropTypes.bool,  // Boolean
        func: React.PropTypes.func, // 函數(shù)
        number: React.PropTypes.number, // 數(shù)字
        string: React.PropTypes.string // 字符串
        ...
    },
     render:function(){ 
        return <div/> 
    }
});
var component = React.render( <Test requiredFunc="bar" bool="true" requiredAny="a"/>,document.body);

mixins

雖然組件的原則就是模塊化,彼此之間相互獨立,但是有時候不同的組件之間可能會存在共享行為,所以 React 提供了 mixins 這種方式來處理這種問題。Mixin 就是用來定義一些方法,使用這個 mixin 的組件能夠自由的使用這些方法,所以 mixin 相當于組件的一個擴展。

// 定義SetIntervalMixin對象
var SetIntervalMixin = {
    componentWillMount: function() {
        this.intervals = [];
    },
    setInterval: function() {
        this.intervals.push(setInterval.apply(null, arguments));
    },
    componentWillUnmount: function() {
        this.intervals.map(clearInterval);
    }
};

var TickTock = React.createClass({
    mixins: [SetIntervalMixin], // 配置mixin數(shù)組,將SetIntervalMixin作為數(shù)組的元素
    getInitialState: function() {
        return {seconds: 0};
    },
    componentDidMount: function() {
        this.setInterval(this.tick, 1000); // 調(diào)用mixin中的setInterval方法
    },
    tick: function() {
        this.setState({seconds: this.state.seconds + 1});
    },
    render: function() {
        return (
            <p>
                React has been running for {this.state.seconds} seconds.
            </p>
        );
    }
});

React.render(
    <TickTock />,
    document.getElementById('example')
);

statics

statics 對象允許你定義靜態(tài)的方法,這些靜態(tài)的方法可以在組件類上調(diào)用。

var MyComponent = React.createClass({ 
    statics: { 
        customMethod: function(foo) { 
            return foo === 'bar'; 
        } 
    }, 
    render: function() {
     }
});
MyComponent.customMethod('bar'); // true

在這個塊兒里面定義的方法都是靜態(tài)的,意味著你可以在任何組件實例創(chuàng)建之前調(diào)用它們,這些方法不能獲取組件的 propsstate。如果你想在靜態(tài)方法中檢查 props 的值,在調(diào)用處把 props 作為參數(shù)傳入到靜態(tài)方法。

displayName

displayName 字符串用于輸出調(diào)試信息。JSX 自動設(shè)置該值;

生命周期方法

組件的生命周期方法會在組件生命周期中某個確定的時間點執(zhí)行。

掛載: componentWillMount

服務(wù)器端和客戶端都只調(diào)用一次,在初始化渲染執(zhí)行之前立刻調(diào)用。如果在這個方法內(nèi)調(diào)用setState,render() 將會感知到更新后的 state,將會執(zhí)行僅一次,盡管 state 改變了。

掛載: componentDidMount

在初始化渲染執(zhí)行之后立刻調(diào)用一次,僅客戶端有效(服務(wù)器端不會調(diào)用)。在生命周期中的這個時間點,組件擁有一個 DOM 展現(xiàn),你可以通過 this.getDOMNode() 來獲取相應(yīng) DOM 節(jié)點。如果想和其它 JavaScript 框架集成,使用 setTimeout 或者 setInterval 來設(shè)置定時器,或者發(fā)送 AJAX 請求,可以在該方法中執(zhí)行這些操作。
注意:為了兼容 v0.9,DOM 節(jié)點作為最后一個參數(shù)傳入。你依然可以通過this.getDOMNode()
獲取 DOM 節(jié)點。

更新: componentWillReceiveProps

componentWillReceiveProps(object nextProps)

在組件接收到新的 props 的時候調(diào)用。在初始化渲染的時候,該方法不會調(diào)用。用此函數(shù)可以作為 react 在 prop 傳入之后, render() 渲染之前更新 state 的機會。老的 props 可以通過 this.props 獲取到。在該函數(shù)中調(diào)用 this.setState() 將不會引起第二次渲染。

componentWillReceiveProps: function(nextProps) { this.setState({ likesIncreasing: nextProps.likeCount > this.props.likeCount });}

注意:對于 state,沒有相似的方法: componentWillReceiveState。將要傳進來的 prop 可能會引起 state 改變,反之則不然。如果需要在 state 改變的時候執(zhí)行一些操作,請使用 componentWillUpdate。

更新: shouldComponentUpdate

boolean shouldComponentUpdate(object nextProps, object nextState)

在接收到新的 props 或者 state,將要渲染之前調(diào)用。該方法在初始化渲染的時候不會調(diào)用,在使用 forceUpdate 方法的時候也不會。如果確定新的 props 和 state 不會導(dǎo)致組件更新,則此處應(yīng)該 返回 false

shouldComponentUpdate: function(nextProps, nextState) { return nextProps.id !== this.props.id;}

如果 shouldComponentUpdate 返回 false,則 render() 將不會執(zhí)行,直到下一次 state 改變。(另外,componentWillUpdate 和 componentDidUpdate 也不會被調(diào)用。)默認情況下,shouldComponentUpdate 總會返回 true,在 state 改變的時候避免細微的 bug,但是如果總是小心地把 state 當做不可變的,在 render() 中只從 props 和state 讀取值,此時你可以覆蓋 shouldComponentUpdate 方法,實現(xiàn)新老 props 和 state 的比對邏輯。如果性能是個瓶頸,尤其是有幾十個甚至上百個組件的時候,使用 shouldComponentUpdate可以提升應(yīng)用的性能。

更新: componentWillUpdate

componentWillUpdate(object nextProps, object nextState)

在接收到新的 props 或者 state 之前立刻調(diào)用。在初始化渲染的時候該方法不會被調(diào)用。使用該方法做一些更新之前的準備工作。
注意:你不能在該方法中使用 this.setState()。如果需要更新 state 來響應(yīng)某個 prop 的改變,請使用 componentWillReceiveProps。

更新: componentDidUpdate

componentDidUpdate(object prevProps, object prevState)

在組件的更新已經(jīng)同步到 DOM 中之后立刻被調(diào)用。該方法不會在初始化渲染的時候調(diào)用。使用該方法可以在組件更新之后操作 DOM 元素。注意:為了兼容 v0.9,DOM 節(jié)點會作為最后一個參數(shù)傳入。如果使用這個方法,你仍然可以使用 this.getDOMNode() 來訪問 DOM 節(jié)點。

移除: componentWillUnmount

在組件從 DOM 中移除的時候立刻被調(diào)用。在該方法中執(zhí)行任何必要的清理,比如無效的定時器,或者清除在 componentDidMount 中創(chuàng)建的 DOM 元素。

參考

【1】《React引領(lǐng)未來的用戶界面開發(fā)框架》
【2】 React中文官網(wǎng)

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

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

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