2018-10-13

react的生命周期(二)

前面已經(jīng)詳細講解過react的生命周期棵里,具體可以參考我的另一篇文章:http://www.reibang.com/p/4be358fadb3d

React組件生命周期有三個階段:加載跑慕、更新和卸載。每個階段有多個方法來調用實現(xiàn)某些功能历极。這些方法名字也很有意思,帶will前綴表示在該階段發(fā)生之前調用,did表示在該階段發(fā)生之后調用。本文將介紹這些方法侣签。本文翻譯自React官網(wǎng)文檔,如有翻譯不當急迂,請不吝指正影所。

1. Mounting階段:

該階段表示一個組件實例被創(chuàng)建并被插入到DOM中。該階段有四個方法:constructor()僚碎,componentWillMount()猴娩,render()和componentDidMount()。

constructor(props):
該方法在組件加載前調用勺阐。當組件作為React.Component的子類實現(xiàn)時需要在其他聲明之前先調用super(props)卷中。否則,this.props在構造器中會是undefined渊抽,這會導致代碼出現(xiàn)bug蟆豫。
作用:
用來初始化狀態(tài),如果既不初始化狀態(tài)也不綁定方法懒闷,那就沒必要實現(xiàn)該方法了十减。(筆者注:事實上,如果組件沒有構造器方法的話愤估,組件會默認調用一個構造器帮辟,實現(xiàn)屬性的傳遞)。
componentWillMount():
該方法會在加載發(fā)生前調用玩焰。因為它發(fā)生在render()方法前由驹,因此在該方法內(nèi)同步設置狀態(tài)不會引發(fā)重渲染。該方法還是服務器端渲染的唯一的生命周期鉤子震捣。一般荔棉,推薦用constructor()代替該方法。
render():
該方法必須要有蒿赢。當調用時润樱,它會檢查this.props和this.state,然后返回一個React元素羡棵。這個元素可以是原生DOM組件如div壹若,也可以是一個自定義的復合組件。如果什么也不想渲染的話,可以返回null或false店展。當返回null或false時养篓,ReactDOM.findDOMNode(this)會返回null。該方法應該是純凈的赂蕴,這意味著它不能修改組件狀態(tài)柳弄,每次調用會返回相同的結果,不會和瀏覽器發(fā)生直接的交互概说。如果想要同瀏覽器發(fā)生交互的話碧注,應該在componentDidMount()中實現(xiàn)。
componentDidMount():組件加載完成后觸發(fā)糖赔。
作用:
放置必要的DOM節(jié)點萍丐。如果要從遠程節(jié)點加載數(shù)據(jù),這是一個不錯的實例化網(wǎng)絡請求的地方放典。也可以在此處設置定時器等逝变。
注意:在該方法內(nèi)設置狀態(tài)會導致重渲染。

2. Updating階段:

該階段表示由狀態(tài)或屬性的改變導致組件的重渲染奋构。該階段有五個方法:componentWillReceiveProps()壳影,shouldComponentUpdate(),componentWillUpdate()弥臼,render()和componentDidUpdate()态贤。

componentWillReceiveProps(nextProps):
該方法會在加載好的組件在收到新的狀態(tài)后調用。如果需要更新狀態(tài)以反映屬性的改變醋火,可以在比較this.props和nextProps后,使用this.setState()方法來實現(xiàn)狀態(tài)的過渡箱吕。
注意:React可能會在props值并未改變的時候調用該方法芥驳,所以要確保每次處理改變時都要比較當前props和收到的props值。這可能發(fā)生在父組件導致該組件重渲染時茬高。
非觸發(fā)時期:mounting階段不會調用該方法兆旬。只有在部分props屬性更新時調用該方法,另外調用this.state()不會觸發(fā)該方法怎栽。
shouldComponentUpdate(nextProps, nextState):該方法用來告訴React,組件輸出是否受到當前狀態(tài)或屬性的影響熏瞄。默認情況下脚祟,每次狀態(tài)改變都會導致重渲染强饮,在大多數(shù)情況下,你只需保持該默認行為即可。該方法在收到新的props或state時會被調用铭乾,且調用是在重渲染前。該方法默認返回true炕檩。但返回false不會影響其子組件在狀態(tài)改變時的重渲染。
非觸發(fā)時期:
初次渲染或使用forceUpdate()時不會調用該方法捌斧。
注意:就目前而言,如果該方法返回false骤星,以后的componentWillUpdate(),render()和componentDidUpdate()都不會再調用了洞难。但未來可能該方法返回的結果只是作為暗示副编,而非指令猖吴,返回false可能仍會導致重新渲染椰棘。
最后根时,如果找到了導致性能低下的組件鸦列,可以使它繼承React.PureComponent谒养。該組件用props和state的淺比較實現(xiàn)了shouldComponentUpdate()桶蝎。也可以自己實現(xiàn)該方法杠娱,通過this.props同nextProps比較编丘,this.state同nextState比較与学,然后返回false以跳過更新。
componentWillUpdate():
該方法在收到新屬性和狀態(tài)渲染前調用嘉抓∷魇兀可以用它來做更新前的準備工作。
注意:
該方法不可以調用this.setState()抑片。如果需要更新狀態(tài)以響應屬性的改變卵佛,使用componentWillReceiveProps(nextProps)代替。
非觸發(fā)時期:初次渲染不會調用該方法敞斋。shouldComponentUpdate()返回false不會調用該方法截汪。
render():
該方法是mount和update階段都會使用到的方法,解釋同mount階段的render()植捎。
非觸發(fā)時期:
shouldComponentUpdate()返回false不會調用該方法衙解。
componentDidUpdate(prevProps, prevState):
更新發(fā)生后會立即調用該方法⊙媸啵可用來在組件更新后操作DOM丢郊。另外盔沫,也可以通過比較當前屬性和之前屬性來決定是否發(fā)送網(wǎng)絡請求(如,狀態(tài)未改變不需要做網(wǎng)絡請求)枫匾。
非觸發(fā)時期:
初次渲染不會調用該方法架诞。shouldComponentUpdate()返回false不會調用該方法。

3. Unmounting階段:
該階段表示組件將從DOM中移除干茉。該階段只有一個方法:componentWillUnmount()谴忧。

componentWillUnmount():
該方法會在組件被銷毀前立即調用。
作用:
可以在方法內(nèi)實現(xiàn)一些清理工作角虫,如清除定時器沾谓,取消網(wǎng)絡請求或者是清理其他在componentDidMount()方法內(nèi)創(chuàng)建的DOM元素。

在組件的整個生命周期中戳鹅,隨著該組件的props或者state發(fā)生改變均驶,它的DOM表現(xiàn)也將有相應的改變,一個組件就是一個狀態(tài)機妇穴,對于特定的輸入腾它,它總會返回一致的輸出死讹。

React為每個組件提供了生命周期鉤子函數(shù)去響應不同的時刻——創(chuàng)建時、存在期及銷毀時妓忍。

生命周期方法

React的組件擁有簡潔的生命周期API愧旦,它僅僅提供你所需要的方法,而不會去最求全面。

實例化:

一個實例出吃被穿件時所調用的生命周期方法與其他哥哥后續(xù)實例被創(chuàng)建所調用的方法略有不同耕皮。當你首次使用一個組建類時蝙场,會看到下面這些方法依次被調用:

getDefaultProps

getInitialState

componentWillMount

render

ComponentDidMOunt

對于該組件類所有后續(xù)應用,你將會看到下面的方法依次被調用罚拟。注意:gerDefaultProps方法不在列表中。

getInitialState

componentWillMount

render

componentDidMount

存在期:

隨著應用狀態(tài)的改變赐俗,以及組件逐漸受到影響,你將會看到下面的方法一次被調用:

componentwillReceiveProps

shouldComponentUpdate

componentWillUpdate

render

componentDidUpdate

銷毀&清理期:

最后粱快,當該組件被使用完成后事哭,componentWillUnmount方法會被調用瓜富,目的是給這個實例提供清理自身的機會。

以下是詳細說明:

實例化:

當每個新的組件被創(chuàng)建首次渲染時谤辜,有一系列的方法可以用來為其做準備工作仅胞,這些方法中的每一個斗毆明確的職責,如下所示:

getDefaultProps

對于組件來說渠欺,這個方法只會調用一次挠将,對于那些沒有父輩組件指定的props屬性的新建實例來說编整,這個方法返回的對象可用與為實例設置默認的props值。

getInitalState:

對于組件的每個實例來說内贮,這個方法調用次數(shù)有且僅有一次汞斧,這里你將有機會初始化每個實例的state,與getDefaultProps方法不同的是,每次實例創(chuàng)建時該方法都會被調用一次竞端,這個方法中庙睡,可以訪問到this.props.

componentWillMount:

該方法在完成首次渲染之前被調用技俐,這也是在render方法調用前可以修改組件state的最后一次機會雕擂。

render:

在這里你創(chuàng)建一個虛擬DOM捂刺,用來表示組件的輸出募寨,對于一個組件來說,render是唯一一個必需的方法仪缸,并且有特定的規(guī)則列肢。render方法選要滿足下面幾點:

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

可以返回null拴还,false或者任何React組件欧聘。

只能出現(xiàn)一個頂級組件(不能返回一組元素)、

必須純凈费封,有位置不能改變組件狀態(tài)或者修改DOM輸出蒋伦。

componentDidMount:

在render方法成功調用并且真實的DOM已經(jīng)被渲染之后痕届,可以在componentDidMount內(nèi)部通過this.getDOMNode(方法訪問到它。

這就是你可以訪問原始DOM的生命周期的鉤子函數(shù)锤窑,當你需要測量DOM元素的高度或者使用計時器操作它或者運行jQuery插件時蓝撇,可以將這些操作掛載到這個方法上:

舉例來說渤昌,假設需要在一個通過React渲染出的表單元素上使用jQueryUI的Autocomplete插件,則可以這樣使用它:

//需要自動補全的字符串列表

var datasource =[...];

var MyComponent=React.crateClass({

render:function(){

rerurn <input .../>

},

componentDidMount:function(){

$(this.gerDOMNode()).autocomplete({

source:datasource

});

}

});

ps:當React運行在服務器端時候迈窟,componentdidmount方法不會被調用忌栅。

存在期:

此時組件已經(jīng)渲染好并且用戶可以與它進行交互,通常一次鼠標點擊湖员、手指點按或者鍵盤事件觸發(fā)一個時間處理器娘摔,隨著用戶改變了組件或則和整個應用的state唤反,便會有新的state流入組件樹,并且我們將會獲得操控它的機會肠缨。

componentWillReceiveProps:

任何時刻組件的props都可以通過父輩組件來更改晒奕,出現(xiàn)這種情況時,componentWillReceiveProps方法會被調用吴汪,你將獲得更改props方法及跟他關心state的機會蒸眠。例如:

componentWillReceiveProps:function(nextProps){

if(nextProps.checked !==undefined){

this.setState({

checked:nextProps.checked

});

}

}

shouleComponentUpdate:

調用shoulecomponentUpadte方法在組件渲染時進行精確優(yōu)化楞卡。如果某個組件或者它的任何子組件不需要渲染成新的props或則和state,則該方法返回false淘捡,返回false則是說明React要跳到render方法焦除,一屆位于render前后的鉤子函數(shù):componentWillUpadate和componentDidUpdate作彤。

該方法非必需的乌逐,并且大部分情況沒有必要使用它浙踢。

componentWillUpdate:

和componentwillMount:方法類似灿渴,組建會在收到新的props或者state進行渲染之前調用該方法。

注意:你不可以在該方法中更新huo或者props蹬挤。而應該借助componentWillreceiveProps方法在運行時更新state荸百。

componentDidUpdate:

和componentDidMount方法類似,該方法給我們更新已經(jīng)渲染好的DOM機會蓝翰。

銷毀&清理期

當React使用完一個組件女嘲,這個組件必須從DOM中卸載隨后被銷毀欣尼。此時僅有的一個狗子函數(shù)會做出響應,完成所有的清理和銷毀工作钙态。

componentWillUnmount:

最后菇晃,隨著組件從他的層級結構中移除,這個組件的生命也就走id熬了盡頭驻子,該方法會在組件被移除之前調用估灿,讓你有機會做一些清理工作。在componentDidMount方法中添加的所有任務都需要在該方法中撤銷域慷,比如穿件的定時器或者添加的事件監(jiān)聽器。

反模式:把計算后的值賦值給state:

getInitalState方法中兄纺,嘗試通過this.props來創(chuàng)建state的做法是一種反模式。React專注于維護數(shù)據(jù)的單一來源钦奋。它的設計使得傳遞數(shù)據(jù)的來源更加顯而易見,這激素和iReact的一個優(yōu)勢朦拖。

比如在組件中吧日期轉化成字符串形式厌衔,或者渲染之前字符串轉換為大寫富寿。這些都不是state,只能夠在渲染時進行計算苏潜。

當組件的state值和它基于的prop不同步变勇,因而無法了解到render函數(shù)內(nèi)部結構時,可以認定為一種反模式飞袋。

//反模式:經(jīng)過計算后值不應該賦給state

getDefaultProps:function(){

return{

date:newDate()

};

},

getInitalState:function(){

return{

day:this.props.date.getDay()

}

},

render:function(){

return <div>Day:{this.state.day}</day>

}

正確的模式應該是渲染時計算這些值巧鸭,保證了計算后的值永遠不會派生出它的props值不同步锣险。

//渲染時計算值是正確的

gerDefaultProps:function(){

return{

date:new Date()

};

}

render:function(){

var day = this.props.date.getDay();

return <div>Day:{day}</div>;

}

然而巷折,如果你的目的并不是同步崖咨,而只是簡單的初始化state,那么在getInitialState方法中使用props是沒問題的署拟,只是一定要明確你的意圖,比如prop添加initial前綴心包。

getDefaultProps:function(){

return{

initialValue:'some-dafault-value'

}馒铃;

},

getInitialState:function(){

return{

value:this.props.initialValue

};

},

render:function(){

return <div>{this.props.value}</div>

}

總結:

react生命周期提供了進行設計的鉤子函數(shù)区宇,會伴隨著組件整個生命周期。和狀態(tài)機類似议谷,每個組件都被設計成了能夠在整個生命周期中輸出穩(wěn)定、語義化的標簽芬首。

組件不會獨立存逼裆,隨著父組件將props推送給他們的子組件,以及那些子組件渲染它們自身的子組件你必須謹慎的考慮數(shù)據(jù)是如何流經(jīng)整個應用的艺晴。每一個子組件真正需要掌握多少數(shù)據(jù)封寞,哪個組件來控制應用的狀態(tài)仅财?這些涉及數(shù)據(jù)流了。


作者:龍波帝國------------------->打造我的IT帝國

歡迎交流盏求,在下扣號:724711690碎罚,請備注:前端技術交流

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荆烈,一起剝皮案震驚了整個濱河市竟趾,隨后出現(xiàn)的幾起案子宫峦,更是在濱河造成了極大的恐慌,老刑警劉巖犀勒,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件账蓉,死亡現(xiàn)場離奇詭異逾一,居然都是意外死亡遵堵,警方通過查閱死者的電腦和手機怨规,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門波丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爽蝴,你說我怎么就攤上這事纫骑∠裙荩” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵梅惯,是天一觀的道長仿野。 經(jīng)常有香客問我,道長徙歼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任桨螺,我火速辦了婚禮灭翔,結果婚禮上辣苏,老公的妹妹穿的比我還像新娘。我一直安慰自己稀蟋,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布骏融。 她就那樣靜靜地躺著档玻,像睡著了一般茫藏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凉当,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天纤怒,我揣著相機與錄音天通,去河邊找鬼。 笑死烘豹,一個胖子當著我的面吹牛诺祸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播憔鬼,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼轴或,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蚕愤?” 一聲冷哼從身側響起饺蚊,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤污呼,失蹤者是張志新(化名)和其女友劉穎燕酷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悟狱,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年双絮,在試婚紗的時候發(fā)現(xiàn)自己被綠了囤攀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡膏萧,死狀恐怖蝌衔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情曹锨,我是刑警寧澤沛简,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站给郊,受9級特大地震影響撒顿,放射性物質發(fā)生泄漏。R本人自食惡果不足惜吩屹,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一煤搜、第九天 我趴在偏房一處隱蔽的房頂上張望擦盾。 院中可真熱鬧淌哟,春花似錦、人聲如沸腐碱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遵蚜。三九已至奈惑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間攒钳,已是汗流浹背雷滋。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姆坚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像腊敲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子懂昂,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • react的生命周期(一) 1.概述 官方簡述版:可參考我的另一篇文章:https://www.jianshu.c...
    龍波帝國閱讀 249評論 0 0
  • 作為一個合格的開發(fā)者,不要只滿足于編寫了可以運行的代碼没宾。而要了解代碼背后的工作原理凌彬;不要只滿足于自己的程序...
    六個周閱讀 8,449評論 1 33
  • React.js 小書學習 之 【使用 JSX 描述 UI 信息】 從 JSX 到頁面 過程圖解:JSX 到頁面過...
    zdlucky閱讀 1,281評論 0 20
  • 原教程內(nèi)容詳見精益 React 學習指南铲敛,這只是我在學習過程中的一些閱讀筆記,個人覺得該教程講解深入淺出会钝,比目前大...
    leonaxiong閱讀 2,840評論 1 18
  • 說在前面 關于 react 的總結過去半年就一直碎碎念著要搞起來伐蒋,各(wo)種(tai)原(lan)因(le)。心...
    陳嘻嘻啊閱讀 6,875評論 7 41