react源碼剖析——(一)生命周期的管理藝術

????????一直想寫react的源碼剖析的文章返弹,由于時間成艘、能力等種種原因一直擱置,近來集中研究了一段時間陳屹老師的《深入react技術椂叩担》蔽挠,感覺有種醍醐灌頂之感,因此計劃寫一個系列的文章瓜浸,從react生命周期澳淑、setState機制、diff剖析插佛、react引擎來介紹下這個可愛的框架杠巡。\(^o^)/~

????????本篇剖析的是react的生命周期,介紹在進入正文之前雇寇,說一說react組件的創(chuàng)建吧氢拥。大家都知道,react有自己的語法JSX谢床,以及為人津津樂道的Virtual DOM兄一,那么他們是怎么被編譯成我們業(yè)務中的組件的呢,實際上通過JSX創(chuàng)建的虛擬元素最終會被編譯成調(diào)用React的createElement方法识腿,而createElement只是做了一個簡單的參數(shù)修正出革,返回一個ReactElement對象這個對象就是將我們的JSX與內(nèi)部方法鏈接起來的紐帶,本文不做過多介紹渡讼,有興趣的話可以去讀一讀源碼骂束。

? ? ? ? 對于React組件耳璧,生命周期是他的核心概念之一。React 的主要思想是通過構(gòu)建可復用組件來構(gòu)建用戶界面展箱。所謂組件其實就是有限狀態(tài)機旨枯,通過狀態(tài)渲染對應的界面,且每個組件都有自己的生命周期混驰,它規(guī)定了組件的狀態(tài)和方法需要在哪個階段進行改變和執(zhí)行攀隔。

????????有限狀態(tài)機(FSM),表示有限個狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動作等行為的模型栖榨。一般通過狀態(tài)昆汹、事件、轉(zhuǎn)換和動作來描述有限狀態(tài)機婴栽,下面是描述組合鎖狀態(tài)機的模型圖满粗,包括5個狀態(tài)、5個狀態(tài)自轉(zhuǎn)換愚争、6個狀態(tài)間轉(zhuǎn)換和1個復位 RESET 轉(zhuǎn)換到狀態(tài) S1映皆。狀態(tài)機,能夠記住目前所處的狀態(tài)轰枝,根據(jù)當前的狀態(tài)可以做出相應的決策捅彻,并且在進入不同的狀態(tài)時,可以做不同的操作狸膏。通過狀態(tài)機將復雜的關系簡單化沟饥,利用這種自然而直觀的方式可以讓代碼更容易理解。


1

????????React 正是利用這一概念湾戳,通過管理狀態(tài)來實現(xiàn)對組件的管理贤旷。例如,某個組件有顯示和隱藏兩個狀態(tài)砾脑,通常會設計兩個方法show()和hide()來實現(xiàn)切換幼驶;而 React 只需要設置狀態(tài)setState({ showed: true/false })即可實現(xiàn)。同時韧衣,React 還引入了組件的生命周期概念盅藻。通過它就可以實現(xiàn)組件的狀態(tài)機控制么鹤,從而達到 “生命周期-狀態(tài)-組件” 的和諧畫面窑眯。

通過實驗,我們得到了生命周期執(zhí)行的順序:

1狂秘、當首次掛載組件時硕噩,順序執(zhí)行:getDefaultProps假残,getInitialState,componentWillMount,render辉懒,componentDidMount 阳惹。

2、當卸載組件時眶俩,執(zhí)行componentWillUnmount莹汤。

3、當重新掛在組件的時颠印,按順序執(zhí)行:getInitialState纲岭,componentWillMount,render嗽仪,componentDidMount荒勇。但是不執(zhí)行getDefaultProps

4、當再次渲染組件時闻坚,組件接收到更新狀態(tài),此時按順序執(zhí)行:componentWillReceiveProps兢孝,shouldComponentUpdate窿凤,componentWillUpdate,render跨蟹,componentDidUpdate雳殊。

2

????????自定義組件(ReactCompositeComponent)的生命周期主要通過三種狀態(tài)進行管理:MOUNTINGRECEIVE_PROPS窗轩、UNMOUNTING夯秃,它們負責通知組件當前所處的狀態(tài),應該執(zhí)行生命周期中的哪個步驟痢艺,是否可以更新 state仓洼。三個狀態(tài)對應三種方法,分別為:mountComponent堤舒、updateComponent色建、unmountComponent,每個方法都提供了兩種處理方法舌缤,will 方法在進入狀態(tài)之前調(diào)用箕戳,did 方法在進入狀態(tài)之后調(diào)用,三種狀態(tài)三種方法五種處理方法国撵,此外還提供兩種特殊狀態(tài)的處理方法陵吸。

? ? ????craetClass是創(chuàng)建自定義組件的入口方法,負責管理生命周期中的getDefaultProps介牙,因此這個方法也將只執(zhí)行一次壮虫,所有實例初始化的props將會被共享。(ps:通過craetClass創(chuàng)建自定義組件耻瑟,利用原型繼承ReactClassComponent父類旨指,按順序合并mixin赏酥,設置初始化defaultProps,返回構(gòu)造函數(shù)谆构,實際上使用es6classes編寫組件時裸扶,class MyCompont extends React.Component實際上就是調(diào)用內(nèi)部方creatClass來創(chuàng)建組件)。下面來詳細剖析一下三個階段:

階段一:MOUNTING

mountComponent負責管理生命周期中的方法:getInitialState搬素、componentWillMount呵晨、render、componentDidMount熬尺。

通過mountComponent掛載組件摸屠,初始化序號、標記等參數(shù)粱哼,判斷是否為無狀態(tài)組件季二,并進行初始化工作,比如初始化props揭措、context等參數(shù)胯舷。利用getInitialState獲取初始化state、初始化更新隊列和更新狀態(tài)绊含。

如果組件中存在componentWillMount桑嘶,則執(zhí)行。如果在componentWillMount中調(diào)用了setState方法躬充,則會進行state合并逃顶,而不是re-render。并且充甚,inst.state = this._processPendingState (inst.props, inst.context) 方法是在componentWillMount之后執(zhí)行的以政,因此componentWillMount方法中的state并不是最新的。

渲染完成后津坑,若存在componentDidMount則調(diào)用妙蔗。這也就是這塊生命周期執(zhí)行順序的由來。?

***PS:mountComponent本質(zhì)上是通過遞歸渲染內(nèi)容的疆瑰,所以父組件的componentWillMount在子組件的componentWillMount之前調(diào)用眉反;父組件的componentDidMount在子組件的componentDidMount之后調(diào)用。


?mountComponent 的執(zhí)行順序

源碼這里就不貼了穆役,感興趣的同學可以自己看書寸五。

階段二:RECEIVE_PROPS

updateComponent負責管理生命周期中的:componentWillReceiveProps、shouldComponentUpdate耿币、componentWillUpdate梳杏、render、componentDidUpdate

若存在componentWillReceiveProps十性,則執(zhí)行叛溢。如果此時在componentWillReceiveProps中調(diào)用setState,是不會觸發(fā)re-render的劲适,而是會進行state合并楷掉。并且,在componentWillReceiveProps霞势、shouldComponentUpdate烹植、componentWillUpdate中也還是無法獲取到更新后的 this.state,只有在render愕贡、componentDidUpdate中才能獲取到更新后的this.state草雕。

同樣的,updateComponent本質(zhì)上也是是通過遞歸渲染內(nèi)容的固以,所以父組件的componentWillUpdate在子組件的componentWillUpdate之前調(diào)用墩虹;父組件的componentDidUpdate在子組件的componentDidUpdate之后調(diào)用。


updateComponent 的執(zhí)行順序

這里有一個需要注意的點:嚴禁在shouldComponentUpdate和componentWillUpdate中調(diào)用setState嘴纺,否則會造成循環(huán)調(diào)用败晴,直至耗光瀏覽器內(nèi)存后崩潰,至于為什么栽渴,下節(jié)會在剖析setState的時候為大家解析。

階段三:UNMOUNTING

unmountComponent負責管理生命周期中的unmountComponent稳懒。

首先將狀態(tài)設置為UNMOUNTING闲擦,若存在 componentWillUnmount,則執(zhí)行并重置所有的相關參數(shù)场梆、更新隊列及更新狀態(tài)墅冷,如果此時在 componentWillUnmount 中調(diào)用setState,是不會觸發(fā) reRender或油。更新狀態(tài)為null寞忿,并清除了公共類,完成組件卸載操作顶岸。

*無狀態(tài)組件

這里提一下無狀態(tài)組件腔彰,無狀態(tài)組件只是一個render方法,沒有狀態(tài)辖佣,沒有生命周期霹抛,只是簡單的接收props渲染生成DOM結(jié)構(gòu),是一個純粹為了渲染而生的組件卷谈。相比于有狀態(tài)組件杯拐,它們簡單快捷高效,所以如果有可能的話,請盡量使用無狀態(tài)組件端逼。

最后歸納一下生命周期:

生命周期全局圖

至此朗兵,本篇文章的剖析結(jié)束,下一篇顶滩,解密setState機制余掖,請關注\(^o^)/~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诲祸,隨后出現(xiàn)的幾起案子浊吏,更是在濱河造成了極大的恐慌,老刑警劉巖救氯,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件找田,死亡現(xiàn)場離奇詭異,居然都是意外死亡着憨,警方通過查閱死者的電腦和手機墩衙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甲抖,“玉大人漆改,你說我怎么就攤上這事∽佳瑁” “怎么了挫剑?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長柱衔。 經(jīng)常有香客問我樊破,道長,這世上最難降的妖魔是什么唆铐? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任哲戚,我火速辦了婚禮,結(jié)果婚禮上艾岂,老公的妹妹穿的比我還像新娘顺少。我一直安慰自己,他們只是感情好王浴,可當我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布脆炎。 她就那樣靜靜地躺著,像睡著了一般叼耙。 火紅的嫁衣襯著肌膚如雪腕窥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天筛婉,我揣著相機與錄音簇爆,去河邊找鬼癞松。 笑死,一個胖子當著我的面吹牛入蛆,可吹牛的內(nèi)容都是我干的响蓉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼哨毁,長吁一口氣:“原來是場噩夢啊……” “哼枫甲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扼褪,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤想幻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后话浇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脏毯,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年幔崖,在試婚紗的時候發(fā)現(xiàn)自己被綠了食店。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡赏寇,死狀恐怖吉嫩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗅定,我是刑警寧澤自娩,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站渠退,受9級特大地震影響椒功,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜智什,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丁屎。 院中可真熱鬧荠锭,春花似錦、人聲如沸晨川。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽共虑。三九已至愧怜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間妈拌,已是汗流浹背拥坛。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工蓬蝶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人猜惋。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓丸氛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親著摔。 傳聞我的和親對象是個殘疾皇子缓窜,可洞房花燭夜當晚...
    茶點故事閱讀 45,573評論 2 359

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