React:組件的生命周期

在組件的整個(gè)生命周期中,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會(huì)有相應(yīng)的變化。一個(gè)組件就是一個(gè)狀態(tài)機(jī),對(duì)于特定地輸入,它總返回一致的輸出。

一個(gè)React組件的生命周期分為三個(gè)部分:實(shí)例化、存在期和銷毀時(shí)。

實(shí)例化

當(dāng)組件在客戶端被實(shí)例化,第一次被創(chuàng)建時(shí),以下方法依次被調(diào)用:

1、getDefaultProps

2、getInitialState

3、componentWillMount

4、render

5、componentDidMount

當(dāng)組件在服務(wù)端被實(shí)例化,首次被創(chuàng)建時(shí),以下方法依次被調(diào)用:

1、getDefaultProps

2、getInitialState

3、componentWillMount

4、render

componentDidMount 不會(huì)在服務(wù)端被渲染的過程中調(diào)用。

getDefaultProps

對(duì)于每個(gè)組件實(shí)例來講,這個(gè)方法只會(huì)調(diào)用一次,該組件類的所有后續(xù)應(yīng)用,getDefaultPops 將不會(huì)再被調(diào)用,其返回的對(duì)象可以用于設(shè)置默認(rèn)的 props(properties的縮寫) 值。

varHello = React.creatClass({getDefaultProps:function(){return{name:'pomy',git:'dwqs'}? ? },render:function(){return(

Hello,{this.props.name},git username is {this.props.dwqs}
)? ? }});ReactDOM.render(, document.body);

也可以在掛載組件的時(shí)候設(shè)置 props:

vardata= [{title: 'Hello'}];

或者調(diào)用?setProps?(一般不需要調(diào)用)來設(shè)置其 props:

vardata= [{title: 'Hello'}];varHello=React.render(, document.body);Hello.setProps({data:data});

但只能在子組件或組件樹上調(diào)用 setProps。別調(diào)用 this.setProps 或者 直接修改 this.props。將其當(dāng)做只讀數(shù)據(jù)。

React通過?propTypes?提供了一種驗(yàn)證 props 的方式,propTypes?是一個(gè)配置對(duì)象,用于定義屬性類型:

varsurvey = 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...? ? },//...})

組件初始化時(shí),如果傳遞的屬性和?propTypes?不匹配,則會(huì)打印一個(gè) console.warn 日志。如果是可選配置,可以去掉.isRequired。常用的 PropTypes 如下:

getInitialState

對(duì)于組件的每個(gè)實(shí)例來說,這個(gè)方法的調(diào)用有且只有一次,用來初始化每個(gè)實(shí)例的 state,在這個(gè)方法里,可以訪問組件的 props。每一個(gè)React組件都有自己的 state,其與 props 的區(qū)別在于 state只存在組件的內(nèi)部,props 在所有實(shí)例中共享。

getInitialState 和 getDefaultPops 的調(diào)用是有區(qū)別的,getDefaultPops 是對(duì)于組件類來說只調(diào)用一次,后續(xù)該類的應(yīng)用都不會(huì)被調(diào)用,而 getInitialState 是對(duì)于每個(gè)組件實(shí)例來講都會(huì)調(diào)用,并且只調(diào)一次。

varLikeButton = React.createClass({getInitialState:function(){return{liked:false};? },handleClick:function(event){this.setState({liked: !this.state.liked});? },render:function(){vartext =this.state.liked ?'like':'haven\'t liked';return(You {text} this. Click to toggle.);? }});ReactDOM.render(,? document.getElementById('example'));

每次修改 state,都會(huì)重新渲染組件,實(shí)例化后通過 state 更新組件,會(huì)依次調(diào)用下列方法:

1、shouldComponentUpdate

2、componentWillUpdate

3、render

4、componentDidUpdate

但是不要直接修改 this.state,要通過 this.setState 方法來修改。

componentWillMount

該方法在首次渲染之前調(diào)用,也是再 render 方法調(diào)用之前修改 state 的最后一次機(jī)會(huì)。

render

該方法會(huì)創(chuàng)建一個(gè)虛擬DOM,用來表示組件的輸出。對(duì)于一個(gè)組件來講,render方法是唯一一個(gè)必需的方法。render方法需要滿足下面幾點(diǎn):

只能通過 this.props 和 this.state 訪問數(shù)據(jù)(不能修改)

可以返回 null,false 或者任何React組件

只能出現(xiàn)一個(gè)頂級(jí)組件,不能返回一組元素

不能改變組件的狀態(tài)

不能修改DOM的輸出

render方法返回的結(jié)果并不是真正的DOM元素,而是一個(gè)虛擬的表現(xiàn),類似于一個(gè)DOM tree的結(jié)構(gòu)的對(duì)象。react之所以效率高,就是這個(gè)原因。

componentDidMount

該方法不會(huì)在服務(wù)端被渲染的過程中調(diào)用。該方法被調(diào)用時(shí),已經(jīng)渲染出真實(shí)的 DOM,可以再該方法中通過?this.getDOMNode()?訪問到真實(shí)的 DOM(推薦使用?ReactDOM.findDOMNode())。

vardata = [..];varcomp = React.createClass({? ? render:function(){return? ? },? ? componentDidMount:function(){? ? ? ? $(this.getDOMNode()).autoComplete({? ? ? ? ? ? src: data? ? ? ? })? ? }})

由于組件并不是真實(shí)的 DOM 節(jié)點(diǎn),而是存在于內(nèi)存之中的一種數(shù)據(jù)結(jié)構(gòu),叫做虛擬 DOM (virtual DOM)。只有當(dāng)它插入文檔以后,才會(huì)變成真實(shí)的 DOM 。有時(shí)需要從組件獲取真實(shí) DOM 的節(jié)點(diǎn),這時(shí)就要用到?ref?屬性:

varArea = React.createClass({? ? render:function(){this.getDOMNode();//render調(diào)用時(shí),組件未掛載,這里將報(bào)錯(cuò)return? ? },? ? componentDidMount:function(){varcanvas =this.refs.mainCanvas.getDOMNode();//這是有效的,可以訪問到 Canvas 節(jié)點(diǎn)}})

需要注意的是,由于?this.refs.[refName]?屬性獲取的是真實(shí) DOM ,所以必須等到虛擬 DOM 插入文檔以后,才能使用這個(gè)屬性,否則會(huì)報(bào)錯(cuò)。

存在期

此時(shí)組件已經(jīng)渲染好并且用戶可以與它進(jìn)行交互,比如鼠標(biāo)點(diǎn)擊,手指點(diǎn)按,或者其它的一些事件,導(dǎo)致應(yīng)用狀態(tài)的改變,你將會(huì)看到下面的方法依次被調(diào)用

1、componentWillReceiveProps

2、shouldComponentUpdate

3、componentWillUpdate

4、render

5、componentDidUpdate

componentWillReceiveProps

組件的 props 屬性可以通過父組件來更改,這時(shí),componentWillReceiveProps 將來被調(diào)用。可以在這個(gè)方法里更新 state,以觸發(fā) render 方法重新渲染組件。

componentWillReceiveProps:function(nextProps){if(nextProps.checked !==undefined){this.setState({? ? ? ? ? ? checked: nextProps.checked? ? ? ? })? ? }}

shouldComponentUpdate

如果你確定組件的 props 或者 state 的改變不需要重新渲染,可以通過在這個(gè)方法里通過返回?false?來阻止組件的重新渲染,返回 `false 則不會(huì)執(zhí)行 render 以及后面的 componentWillUpdate,componentDidUpdate 方法。

該方法是非必須的,并且大多數(shù)情況下沒有在開發(fā)中使用。

shouldComponentUpdate:function(nextProps, nextState){returnthis.state.checked === nextState.checked;//return false 則不更新組件}

componentWillUpdate

這個(gè)方法和 componentWillMount 類似,在組件接收到了新的 props 或者 state 即將進(jìn)行重新渲染前,componentWillUpdate(object nextProps, object nextState) 會(huì)被調(diào)用,注意不要在此方面里再去更新 props 或者 state。

componentDidUpdate

這個(gè)方法和 componentDidMount 類似,在組件重新被渲染之后,componentDidUpdate(object prevProps, object prevState) 會(huì)被調(diào)用。可以在這里訪問并修改 DOM。

銷毀時(shí)

componentWillUnmount

每當(dāng)React使用完一個(gè)組件,這個(gè)組件必須從 DOM 中卸載后被銷毀,此時(shí) componentWillUnmout 會(huì)被執(zhí)行,完成所有的清理和銷毀工作,在 componentDidMount 中添加的任務(wù)都需要再該方法中撤銷,如創(chuàng)建的定時(shí)器或事件監(jiān)聽器。

當(dāng)再次裝載組件時(shí),以下方法會(huì)被依次調(diào)用:

1、getInitialState

2、componentWillMount

3、render

4、componentDidMount

反模式

在 getInitialState 方法中,嘗試通過 this.props 來創(chuàng)建 state 的做法是一種反模式。

//反模式getDefaultProps:function(){return{data:newDate()? ? }},getInitialState:function(){return{day:this.props.date -newDate()? ? }},render:function(){return

Day:{this.state.day}
}

經(jīng)過計(jì)算后的值不應(yīng)該賦給 state,正確的模式應(yīng)該是在渲染時(shí)計(jì)算這些值。這樣保證了計(jì)算后的值永遠(yuǎn)不會(huì)與派生出它的 props 值不同步。

//正確模式getDefaultProps:function(){return{data:newDate()? ? }},render:function(){varday =this.props.date -newDate();return

Day:{day}
}

如果只是簡單的初始化 state,那么應(yīng)用反模式是沒有問題的。

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

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

  • 在組件的整個(gè)生命周期中,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會(huì)有相應(yīng)的變化。一個(gè)組件就是一...
    CLYDE_6715閱讀 232評(píng)論 0 0
  • 作為一個(gè)合格的開發(fā)者,不要只滿足于編寫了可以運(yùn)行的代碼。而要了解代碼背后的工作原理;不要只滿足于自己的程序...
    六個(gè)周閱讀 8,679評(píng)論 1 33
  • 在組件的整個(gè)生命周期中,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會(huì)有相應(yīng)的變化。一個(gè)組件就是一...
    cici_7a32閱讀 833評(píng)論 0 0
  • 在組件的整個(gè)生命周期中,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會(huì)有相應(yīng)的變化。一個(gè)組件就是一...
    淙淙_5719閱讀 361評(píng)論 0 0
  • 在組件的整個(gè)生命周期中,隨著該組件的props或者state發(fā)生改變,其DOM表現(xiàn)也會(huì)有相應(yīng)的變化。一個(gè)組件就是一...
    konner_5d7d閱讀 348評(píng)論 0 0

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