2、深入淺出React(二)組件的生命周期

3. 組件生命周期

  • React嚴格定義了組件的生命周期,生命周期可能會經(jīng)歷如下三個過程:
  • 裝載過程(Mount):也就是把組件第一次在DOM樹上渲染的過程;
  • 更新過程(Updata):當組件被從新渲染的過程;
  • 卸載過程(Unmount):組件從DOM樹中刪除的過程。
  1. 三種不同的過程,React庫會調(diào)用組件的一些成員函數(shù),即生命周期函數(shù)。

3.1、裝載過程

  • 當組件第一次被渲染時,依次調(diào)用的函數(shù):
  • construction
  • getInitalState
  • getDefaultProps
  • componentWillMount
  • render
  • componentDidMount
  1. constructor

ES6中每個類的構(gòu)造函數(shù),要創(chuàng)建一個組件類的實例,便會調(diào)用對應(yīng)的構(gòu)造函數(shù)
注意:

  1. 并不是每個組件都需要定義自己的構(gòu)造函數(shù),無狀態(tài)的React組件往往就不需要定義構(gòu)造
    函數(shù);
  2. 一個React組件需要構(gòu)造函數(shù)目的:
  • 初始化state,因為組件的生命周期中任何函數(shù)都可能要訪問state,那么整個周期中第一個被調(diào)用的構(gòu)造函數(shù)便是初始化state最理想的地方;
  • 綁定成員函數(shù)的this環(huán)境:
    • 因為在ES6語法下,類的每個成員函數(shù)在執(zhí)行時的this并不是和類實例自動綁定的;
    • 而在構(gòu)造函數(shù)中this就是當前組件實例,所以,為了方便將來調(diào)用,往往在構(gòu)造函數(shù)中將這個實例的特定函數(shù)綁定this為當前類實例:
```
   ...
   constructor(props){
      super(props);
      
      this.onClickFunc = this.onClickFunc.bind(this);
   }
 ```
  1. getInitialState和getDefaultProps

    1. getInitialState函數(shù)的返回值用來初始化組件的this.state;
    2. getInitialState只出現(xiàn)在裝載過程,也就是說一個組件的整個生命周期過程中,這個函數(shù)只被調(diào)用一次;
    3. getDefaultProps函數(shù)的返回值可以作為props的初始值;
    4. 兩個函數(shù)都只有在使用React.createClass方法創(chuàng)建組件類時才會用到
     const Sample = React.createClass({
       getInitialState: function() {
         return {foo: '返回值將作為this.state的初始值'};
       },
       getDefaultProps: function() {
         return {sampleProp: '作為props的初始值'}
       }
     })
    
    1. React.createClass創(chuàng)建方法已經(jīng)逐漸被Facebook官方廢棄
    2. 使用ES6時,在構(gòu)造函數(shù)中通過this.state賦值完成狀態(tài)初始化;通過給類屬性(注意是類屬性,而不是類的實例對象的屬性)defaultProps賦值指定的props初始值:
    
    class Sample extends React.Component{
      constructor (props){
        super(props);
        this.state = {foo: '初始值'}
      }
    }
    Sample.defaultProps = {
      sampleProps: 0
    }
    
    
    
  2. render

  • render函數(shù)是React組件中最重要的函數(shù),一個React組件可以忽略其他所有函數(shù)都不實現(xiàn),但一定要實現(xiàn)render函數(shù),因為所有React組件的父類React.Component類對除了render之外的生命周期函數(shù)都有默認實現(xiàn)。

  • 通常一個組件要發(fā)揮作用,總是要渲染一些東西,render函數(shù)并不做實際的渲染動作,它只是返回一個JSX描述結(jié)構(gòu),最終由React來操作渲染過程;

  • 當某個特殊的組件作用不是渲染界面,或者沒有東西可畫時,可讓render函數(shù)返回null或者false,即告訴React此組件不渲染任何DOM元素;

  • 注意:render函數(shù)應(yīng)該是一個純函數(shù),完全根據(jù)this.state和this.props來決定返回的結(jié)果,而且不要產(chǎn)生任何副作用,不要在render函數(shù)中調(diào)用this.setState去改變狀態(tài),因為一個純函數(shù)不應(yīng)該引起狀態(tài)的改變。

  1. componentWillMount和componentDidMount
  • 在裝載過程中,componentWillMount會在render函數(shù)之前調(diào)用,此時還沒有任何東西渲染出來,即使調(diào)用this.setState修改狀態(tài)也不會發(fā)生重新繪制;

  • componentDidMount在render函數(shù)之后調(diào)用,但render調(diào)用之后并不會立即調(diào)用,而是在render函數(shù)返回的東西已經(jīng)引發(fā)了渲染,組件已經(jīng)被‘裝載’到了DOM樹上后,componentDidMount才被調(diào)用,此時已繪制出真實的DOM樹;

  • 注意:

  1. render函數(shù)本身并不往DOM樹上渲染或者裝載內(nèi)容,它只是返回一個表示JSX表示的對象(及組件實例),然后由React庫根據(jù)返回的對象決定如何渲染;
  2. 而React庫肯定是要把所有組件返回的結(jié)果綜合起來,才能知道如何產(chǎn)生對應(yīng)的DOM修改;
  3. 所以只有React庫調(diào)用所有組件的render函數(shù)之后,才有可能完成DOM裝載,這時候才會依調(diào)用componentDidMount函數(shù)作為裝載的收尾。
  4. componentWillMount可以在服務(wù)器和瀏覽器端被調(diào)用,而componentDidMount只能在瀏覽器端被調(diào)用(因為componentDidMount是在‘裝載’完成之后被調(diào)用,且‘裝載’是一個創(chuàng)建組件并放到DOM樹上的過程,而服務(wù)器端渲染通過React組件產(chǎn)生的只是一個純粹的字符串,并不會產(chǎn)生DOM樹,即在服務(wù)器端不可能完成‘裝載過程’所以無法調(diào)用componentDidMount)

3.2、更新過程

  • 隨著用戶的操作改變展示的內(nèi)容,當props或者state被修改時,就會引發(fā)組件的更新過程;
  • 更新過程會依次調(diào)用以下生命周期函數(shù),其中render函數(shù)和“裝載”過程一樣:
    • componentWillReceiveProps
    • shouldComponentUpdate
    • componentWillUpdate
    • render
    • componentDidUpdate
  • 并不是所有的更新過程都會執(zhí)行全部函數(shù)。
  1. componentWillReceiveProps(nextProps)
  • 并不是只有在組件的props發(fā)生改變的時候才會調(diào)用此函數(shù);
  • 在更新過程,只要是父組件的render函數(shù)被調(diào)用,在render函數(shù)里被渲染的子組件就會經(jīng)歷更新過程,不管父組件傳給子組件的props有沒有改變,都會觸發(fā)子組件的componentWillReceiveProps函數(shù);
  • 注意:通過this.setState方法觸發(fā)的更新過程不會調(diào)用這個函數(shù);
  • 因為,這個函數(shù)適合根據(jù)新的props值(也就是參數(shù)nextProps)來計算是不是要更新內(nèi)部狀態(tài)state;而更新內(nèi)部狀態(tài)的方法是this.setState,如果this.setState的調(diào)用導(dǎo)致componentWillReceiveProps再調(diào)用,那將是一個死循環(huán)。
  1. shouldComponentUpdate(nextProps,nextState)
  • 除了render函數(shù),shouleComponentUpdate可能是生命周期函數(shù)中最重要的一個函數(shù);
  • 因為render函數(shù)決定了該渲染什么,shouldComponentUpdate決定了一個組件什么時候不需要渲染;
  • render和shouldComponentUpdate也是React生命周期函數(shù)中唯二兩個要求有返回結(jié)果的函數(shù);
  • render函數(shù)的返回結(jié)果用于構(gòu)建DOM對象,shouldComponentUpdate函數(shù)返回一個布爾值,告訴React庫這個組件這次更新過程是否繼續(xù);
  • 在更新過程中,React庫首先調(diào)用shouldComponentUpdate函數(shù),如果這個函數(shù)返回true,那就繼續(xù)更新過程,接下來調(diào)用render,反之則終止此次更新過程;
  • shouldComponentUpdate的參數(shù)就是接下來的props和state值;我們可以根據(jù)這兩個參數(shù),外加this.props和this.state來判斷返回true或false,從而避免不必要的更新。
  1. componentWillUpdate和componentDidUpdate
  • 如果組件的shouldComponentUpdate返回true,React接下來調(diào)用componentWillUpdate、render和componentDidUpdate;
  • 和“裝載”過程不同,這對函數(shù)都可以在服務(wù)器和瀏覽器更新階段調(diào)用
  • 不過,通常在使用React做服務(wù)端渲染時,基本不會經(jīng)歷更新過程,因為服務(wù)器端只需要產(chǎn)出HTML字符串,而一個裝載過程就足夠產(chǎn)出HTML字符串了,所以正常情況下,服務(wù)器端不會調(diào)用componentDidUpdate函數(shù),如果調(diào)用了,說明程序有錯,需要改進。

3.2、卸載過程

  • React組件的卸載過程只涉及一個函數(shù)componentWillUnmount,
  • 當React組件要從DOM樹上刪除之前,對應(yīng)的componentWillUnmount函數(shù)會被調(diào)用,所以這個函數(shù)適合做一些清理性的工作。

持續(xù)更新中……喜歡請點個贊哦~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

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