在組件的整個生命週期中,隨着該組件的props或者state發生改變,其DOM表現也會有相應的變化。一個組件就是一個狀態機,對於特定地輸入,它總返回一致的輸出。html
一個React組件的生命週期分爲三個部分:實例化、存在期和銷燬時。react
當組件在客戶端被實例化,第一次被建立時,如下方法依次被調用:git
一、getDefaultProps
二、getInitialState
三、componentWillMount
四、render
五、componentDidMountcanvas
當組件在服務端被實例化,首次被建立時,如下方法依次被調用:數據結構
一、getDefaultProps
二、getInitialState
三、componentWillMount
四、renderui
componentDidMount 不會在服務端被渲染的過程當中調用。this
對於每一個組件實例來說,這個方法只會調用一次,該組件類的全部後續應用,getDefaultPops 將不會再被調用,其返回的對象能夠用於設置默認的 props(properties的縮寫) 值。spa
var Hello = React.creatClass({ getDefaultProps: function(){ return { name: 'pomy', git: 'dwqs' } }, render: function(){ return ( <div>Hello,{this.props.name},git username is {this.props.dwqs}</div> ) } }); ReactDOM.render(<Hello />, document.body);
也能夠在掛載組件的時候設置 props:日誌
var data = [{title: 'Hello'}]; <Hello data={data} />
或者調用 setProps
(通常不須要調用)來設置其 props:code
var data = [{title: 'Hello'}]; var Hello = React.render(<Demo />, document.body); Hello.setProps({data:data});
但只能在子組件或組件樹上調用 setProps。別調用 this.setProps 或者 直接修改 this.props。將其當作只讀數據。
React經過 propTypes
提供了一種驗證 props 的方式,propTypes
是一個配置對象,用於定義屬性類型:
var survey = React.createClass({ propTypes: { survey: React.PropTypes.shape({ id: React.PropTypes.number.isRequired }).isRequired, onClick: React.PropTypes.func, name: React.PropTypes.string, score: React.PropTypes.array ... }, //... })
組件初始化時,若是傳遞的屬性和 propTypes
不匹配,則會打印一個 console.warn 日誌。若是是可選配置,能夠去掉.isRequired。經常使用的 PropTypes 以下:
對於組件的每一個實例來講,這個方法的調用有且只有一次,用來初始化每一個實例的 state,在這個方法裏,能夠訪問組件的 props。每個React組件都有本身的 state,其與 props 的區別在於 state只存在組件的內部,props 在全部實例中共享。
getInitialState 和 getDefaultPops 的調用是有區別的,getDefaultPops 是對於組件類來講只調用一次,後續該類的應用都不會被調用,而 getInitialState 是對於每一個組件實例來說都會調用,而且只調一次。
var LikeButton = React.createClass({ getInitialState: function() { return {liked: false}; }, handleClick: function(event) { this.setState({liked: !this.state.liked}); }, render: function() { var text = this.state.liked ? 'like' : 'haven\'t liked'; return ( <p onClick={this.handleClick}> You {text} this. Click to toggle. </p> ); } }); ReactDOM.render( <LikeButton />, document.getElementById('example') );
每次修改 state,都會從新渲染組件,實例化後經過 state 更新組件,會依次調用下列方法:
一、shouldComponentUpdate
二、componentWillUpdate
三、render
四、componentDidUpdate
可是不要直接修改 this.state,要經過 this.setState 方法來修改。
該方法在首次渲染以前調用,也是再 render 方法調用以前修改 state 的最後一次機會。
該方法會建立一個虛擬DOM,用來表示組件的輸出。對於一個組件來說,render方法是惟一一個必需的方法。render方法須要知足下面幾點:
只能經過 this.props 和 this.state 訪問數據(不能修改)
能夠返回 null,false 或者任何React組件
只能出現一個頂級組件,不能返回一組元素
不能改變組件的狀態
不能修改DOM的輸出
render方法返回的結果並非真正的DOM元素,而是一個虛擬的表現,相似於一個DOM tree的結構的對象。react之因此效率高,就是這個緣由。
該方法不會在服務端被渲染的過程當中調用。該方法被調用時,已經渲染出真實的 DOM,能夠再該方法中經過 this.getDOMNode()
訪問到真實的 DOM(推薦使用 ReactDOM.findDOMNode()
)。
var data = [..]; var comp = React.createClass({ render: function(){ return <imput .. /> }, componentDidMount: function(){ $(this.getDOMNode()).autoComplete({ src: data }) } })
因爲組件並非真實的 DOM 節點,而是存在於內存之中的一種數據結構,叫作虛擬 DOM (virtual DOM)。只有當它插入文檔之後,纔會變成真實的 DOM 。有時須要從組件獲取真實 DOM 的節點,這時就要用到 ref
屬性:
var Area = React.createClass({ render: function(){ this.getDOMNode(); //render調用時,組件未掛載,這裏將報錯 return <canvas ref='mainCanvas'> }, componentDidMount: function(){ var canvas = this.refs.mainCanvas.getDOMNode(); //這是有效的,能夠訪問到 Canvas 節點 } })
須要注意的是,因爲 this.refs.[refName]
屬性獲取的是真實 DOM ,因此必須等到虛擬 DOM 插入文檔之後,才能使用這個屬性,不然會報錯。
此時組件已經渲染好而且用戶能夠與它進行交互,好比鼠標點擊,手指點按,或者其它的一些事件,致使應用狀態的改變,你將會看到下面的方法依次被調用
一、componentWillReceiveProps
二、shouldComponentUpdate
三、componentWillUpdate
四、render
五、componentDidUpdate
組件的 props 屬性能夠經過父組件來更改,這時,componentWillReceiveProps 未來被調用。能夠在這個方法裏更新 state,以觸發 render 方法從新渲染組件。
componentWillReceiveProps: function(nextProps){ if(nextProps.checked !== undefined){ this.setState({ checked: nextProps.checked }) } }
若是你肯定組件的 props 或者 state 的改變不須要從新渲染,能夠經過在這個方法裏經過返回 false
來阻止組件的從新渲染,返回 `false 則不會執行 render 以及後面的 componentWillUpdate,componentDidUpdate 方法。
該方法是非必須的,而且大多數狀況下沒有在開發中使用。
shouldComponentUpdate: function(nextProps, nextState){ return this.state.checked === nextState.checked; //return false 則不更新組件 }
這個方法和 componentWillMount 相似,在組件接收到了新的 props 或者 state 即將進行從新渲染前,componentWillUpdate(object nextProps, object nextState) 會被調用,注意不要在此方面裏再去更新 props 或者 state。
這個方法和 componentDidMount 相似,在組件從新被渲染以後,componentDidUpdate(object prevProps, object prevState) 會被調用。能夠在這裏訪問並修改 DOM。
每當React使用完一個組件,這個組件必須從 DOM 中卸載後被銷燬,此時 componentWillUnmout 會被執行,完成全部的清理和銷燬工做,在 componentDidMount 中添加的任務都須要再該方法中撤銷,如建立的定時器或事件監聽器。
當再次裝載組件時,如下方法會被依次調用:
一、getInitialState
二、componentWillMount
三、render
四、componentDidMount
在 getInitialState 方法中,嘗試經過 this.props 來建立 state 的作法是一種反模式。
//反模式 getDefaultProps: function(){ return { data: new Date() } }, getInitialState: function(){ return { day: this.props.date - new Date() } }, render: function(){ return <div>Day:{this.state.day}</div> }
通過計算後的值不該該賦給 state,正確的模式應該是在渲染時計算這些值。這樣保證了計算後的值永遠不會與派生出它的 props 值不一樣步。
//正確模式 getDefaultProps: function(){ return { data: new Date() } }, render: function(){ var day = this.props.date - new Date(); return <div>Day:{day}</div> }
若是隻是簡單的初始化 state,那麼應用反模式是沒有問題的。
如下面的一張圖總結組件的生命週期: