React 組件的生命周期

React 組件的一生海渊,是光榮的一生,是革命的一生,在它的一生中會經(jīng)歷這樣幾個階段:

  • 裝載階段
  • 更新階段
  • 銷毀階段

每一階段都會觸發(fā)相應(yīng)的生命周期函數(shù)贮乳,下面依次來說一說這些生命周期函數(shù)。

裝載階段

裝載階段就是組件第一次被渲染時的階段恬惯,這一階段相關(guān)的生命周期函數(shù)有:

  • constructor
  • componentWillMount
  • render
  • componentDidMount

下面是這些方法的一些說明:
constructor:用來初始化組件向拆,獲取組件的初始屬性(props)或狀態(tài)(state),其作用類似于 ES5 createClass 寫法中的 getInitialState 和 getDefaultProps 函數(shù)酪耳。
componentWillMount:在組件即將裝載前調(diào)用浓恳。
render:用來生成一個 JSX 描述結(jié)構(gòu)刹缝,告訴 React 本次要裝載哪些東西,需要注意的是颈将,render方法只用來返回一個 JSX 結(jié)構(gòu)梢夯,并不負責裝載,具體的裝載工作由 React 完成晴圾。
componentDidMount:在組件被裝載之后調(diào)用颂砸,此時已經(jīng)完成了 DOM 更新,組件已經(jīng)被裝載到真實的 DOM 樹中了死姚,可以進行相應(yīng)的 DOM 操作人乓,比如添加原生的 DOM 事件就應(yīng)該放在 componentDidMount 中進行。
看一個例子:

import React,{ Component } from "react";
import "./App.css";

export default class App extends Component{
    constructor(props){
        super(props);
        console.log("constructor")
    }

    componentWillMount() {
        console.log("componentWillMount")
    }

    componentDidMount(){
        console.log("componentDidMount")
    }

    render(){
        console.log("render")
        return(
            <div className = "App-div">
                
            </div>
        );
    }
}

打開瀏覽器都毒,控制臺中輸出的結(jié)果為:

constructor
componentWillMount
render
componentDidMount

多個組件的情況

如果 App 組件中渲染了其他的組件色罚,那么這些組件的生命周期函數(shù)是怎樣調(diào)用的呢?
新建一個 SubComponent.js:

import React,{ Component } from "react";

export default class Sub extends Component{
    constructor(props){
        super(props);
        console.log("constructor")
    }

    componentWillMount() {
        console.log("componentWillMount")
    }

    componentDidMount(){
        console.log("componentDidMount")
    }

    render(){
        console.log("render")
        return(
            <div>我是子組件</div>
        );
    }
}

修改 App.js温鸽,讓其渲染兩個子組件:

import React,{ Component } from "react";
import Sub from "./SubComponent.js";
import "./App.css";

export default class App extends Component{
    
    render(){
        const SubArr = [1,2].map((v)=>{
            return <Sub key = {v} />
        });

        return(
            <div className = "App-div">
                { SubArr }
            </div>
        );
    }
}

打開瀏覽器保屯,看下控制臺中的輸出:

constructor
componentWillMount
render
constructor
componentWillMount
render
componentDidMount
componentDidMount

這兩個子組件的 componentDidMount 函數(shù)并不是在 render 函數(shù)之后執(zhí)行,而是放在最后執(zhí)行了涤垫,為什么呢姑尺?
還是回到上面那句話:render 函數(shù)只用來生成 JSX 組件結(jié)構(gòu),不負責裝載工作蝠猬,具體的狀態(tài)工作交個 React 完成切蟋。
React 需要在形成完整的 JSX 結(jié)構(gòu)之后才進行裝載,也就是說榆芦,要在兩個 render 函數(shù)都調(diào)用完成后才進行裝載工作柄粹,而后再調(diào)用 componentDidMount 生命周期函數(shù)。

更新階段

如果組件中的 state 或者 props 發(fā)生了改變匆绣,React 就會更新該組件驻右,此時會調(diào)用更新階段中相關(guān)的生命周期函數(shù):

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

componentWillReceiveProps 函數(shù)在傳遞給子組件的 props 變化或者父組件更新時調(diào)用。
修改 SubComponent.js:

import React,{ Component } from "react";

export default class Sub extends Component{
    componentWillReceiveProps(nextProps) {
        console.log("componentWillReceiveProps");
    }

    shouldComponentUpdate(nextProps, nextState) {
        console.log("shouldComponentUpdate");
        return true;
    }

    componentDidUpdate(prevProps, prevState) {
        console.log("componentDidUpdate");
    }

    render(){
        console.log("render")
        return(
            <div>我是子組件</div>
        );
    }
}

修改 App.js崎淳,增加一個按鈕堪夭,點擊時強制更新:

import React,{ Component } from "react";
import Sub from "./SubComponent.js";
import "./App.css";

export default class App extends Component{

    render(){
        const SubArr = [1,2].map((v)=>{
            return <Sub key = {v} />
        });

        return(
            <div className = "App-div">
                <button onClick = { ()=>this.forceUpdate() }>點擊強制更新</button>
                { SubArr }
            </div>
        );
    }
}

點擊更新按鈕,看下控制臺的輸出:

componentWillReceiveProps
shouldComponentUpdate
render
componentWillReceiveProps
shouldComponentUpdate
render
componentDidUpdate
componentDidUpdate

可見拣凹,父組件的更新也會引起子組件的更新森爽,如果父組件中有很多子組件,默認情況下嚣镜,在父組件進行更新(通常是父組件的 props 或 state 發(fā)生變化)或者父組件傳遞給子組件的 props 發(fā)生變化時爬迟,會引起所有子組件的更新。如果子組件數(shù)量眾多菊匿,功能復(fù)雜付呕,那么進行更新會產(chǎn)生大量的性能浪費计福,即使是在使用 Virtual DOM 的情況下。針對這種情況徽职,我們就需要使用下面介紹的 shouldComponentUpdate 函數(shù)了棒搜。
P.S.在使用 setState 時并不會調(diào)用 componentWillReceiveProps,而是直接調(diào)用 shouldComponentUpdate 函數(shù)活箕。

shouldComponentUpdate 函數(shù)接受兩個參數(shù):nextProps 和 nextState,分別表示引發(fā)本次組件更新的 props 或 state可款,該函數(shù)的返回值的真假決定組件是否更新育韩,默認返回 true。實際應(yīng)用場景中闺鲸,我們可以將這兩個參數(shù)和組件當前的 props(this.props)和當前的 state(this.state)進行比對筋讨,以決定是否更新組件,提高性能摸恍。
為了方便演示悉罕,給每個子組件傳遞一個名為 flag 的 prop:

import React,{ Component } from "react";
import Sub from "./SubComponent.js";
import "./App.css";

export default class App extends Component{

    render(){
        const SubArr = [1,2].map((v)=>{
            return <Sub key = {v} flag = "1" />
        });

        return(
            <div className = "App-div">
                <button onClick = { ()=>this.forceUpdate() }>點擊強制更新</button>
                { SubArr }
            </div>
        );
    }
}

修改 SubComponent.js:

import React,{ Component } from "react";

export default class Sub extends Component{
    componentWillReceiveProps(nextProps) {
        console.log("componentWillReceiveProps");
    }

    shouldComponentUpdate(nextProps, nextState) {
        return (nextProps.flag !== this.props.flag);
    }

    componentDidUpdate(prevProps, prevState) {
        console.log("componentDidUpdate");
    }

    render(){
        console.log("render")
        return(
            <div>我是子組件</div>
        );
    }
}

控制臺的輸出結(jié)果為:

componentWillReceiveProps
componentWillReceiveProps

父組件更新后,會引起子組件的更新立镶,首先就是調(diào)用 componentWillReceiveProps 方法壁袄,之后在 shouldComponentUpdate 中進行屬性值的判斷,由于兩次渲染都傳遞了相同的屬性值媚媒,因此沒有必要更新組件嗜逻,shouldComponentUpdate 函數(shù)返回 false,后面的一系列生命周期函數(shù)就不執(zhí)行了缭召,提高了渲染性能栈顷。
componentWillUpdate 函數(shù)在組件即將更新時調(diào)用。
render 函數(shù)用來產(chǎn)出本次更新的 JSX 組件樹結(jié)構(gòu)嵌巷。
componentDidUpdate 函數(shù)在組件完成更新后調(diào)用萄凤。當組件被更新時,會重新繪制 DOM 樹搪哪。同 componentDidMount 函數(shù)靡努,該函數(shù)并不是在每個子組件 render 方法執(zhí)行后立即被執(zhí)行的,而是等待 DOM 樹更新后再執(zhí)行噩死。

卸載過程

卸載過程就一個函數(shù):

  • componentWillUnmount

該函數(shù)用來做一些清理工作颤难,比如如果在組件中使用了原生的 DOM 事件,需要在組件被銷毀前移除該事件已维,防止內(nèi)存泄露行嗤,或者清理定時器等。

完垛耳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末栅屏,一起剝皮案震驚了整個濱河市飘千,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌栈雳,老刑警劉巖护奈,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哥纫,居然都是意外死亡霉旗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門蛀骇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厌秒,“玉大人,你說我怎么就攤上這事擅憔⊥疑粒” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵暑诸,是天一觀的道長蚌讼。 經(jīng)常有香客問我,道長个榕,這世上最難降的妖魔是什么篡石? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮西采,結(jié)果婚禮上夏志,老公的妹妹穿的比我還像新娘。我一直安慰自己苛让,他們只是感情好沟蔑,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狱杰,像睡著了一般瘦材。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仿畸,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天食棕,我揣著相機與錄音,去河邊找鬼错沽。 笑死簿晓,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的千埃。 我是一名探鬼主播憔儿,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼放可!你這毒婦竟也來了谒臼?” 一聲冷哼從身側(cè)響起朝刊,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜈缤,沒想到半個月后拾氓,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡底哥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年咙鞍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趾徽。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奶陈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出附较,到底是詐尸還是另有隱情,我是刑警寧澤潦俺,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布拒课,位于F島的核電站,受9級特大地震影響事示,放射性物質(zhì)發(fā)生泄漏早像。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一肖爵、第九天 我趴在偏房一處隱蔽的房頂上張望卢鹦。 院中可真熱鬧,春花似錦劝堪、人聲如沸冀自。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熬粗。三九已至,卻和暖如春余境,著一層夾襖步出監(jiān)牢的瞬間驻呐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工芳来, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留含末,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓即舌,卻偏偏與公主長得像佣盒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子顽聂,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

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

  • 組件的生命周期 組件在react的生命周期中主要經(jīng)歷三個階段:實例化沼撕、存在期和銷毀時宋雏。React.js在組件生命周...
    落花的季節(jié)閱讀 573評論 0 2
  • React組件生命周期4個階段:創(chuàng)建階段、實例化階段务豺、更新階段磨总、銷毀階段 【創(chuàng)建階段】● getDefaultPr...
    mayunyun閱讀 243評論 0 0
  • 一般來說,一個組件類由 extends Component 創(chuàng)建笼沥,并且提供一個 render 方法以及其他可選的生...
    ElineC閱讀 643評論 0 2
  • 006@React組件的生命周期.md React Native 是基于組件化開發(fā)蚪燕。弄清楚組件的生命周期對于我們開...
    驀然之間的閱讀 417評論 1 0
  • 理解React組件的生命周期 本文作者寫作的時間較早,所以里面會出現(xiàn)很多的舊版ES5的時代的方法奔浅。不過馆纳,雖然如此并...
    uncle_charlie閱讀 1,641評論 0 2