[React] render中進(jìn)行diff

場(chǎng)景

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class A extends Component {
    componentWillMount() {
        console.log('A: componentWillMount');
    }

    render() {
        console.log('A: render');

        return (
            <div>
                <div>456</div>
                <div>A{this.props.a}</div>
            </div>
        );
    }

    componentDidMount() {
        console.log('A: componentDidMount');
    }

    componentWillReceiveProps() {
        console.log('A: componentWillReceiveProps');
    }

    shouldComponentUpdate() {
        console.log('A: shouldComponentUpdate');
        return true;
    }

    componentWillUpdate() {
        console.log('A: componentWillUpdate');
    }

    // render

    componentDidUpdate() {
        console.log('A: componentDidUpdate');
    }
}

class Page extends Component {
    state = {
        a: 1
    };

    componentWillMount() {
        console.log('Page: componentWillMount');
    }

    render() {
        console.log('Page: render');

        return (
            <div>
                <div>123</div>
                <A a={this.state.a} />
            </div>
        );
    }

    componentDidMount() {
        console.log('Page: componentDidMount');

        setTimeout(() => {
            console.warn('Page: setState');
            this.setState({
                a: 1
            });
        }, 2000);
    }

    componentWillReceiveProps() {
        console.log('Page: componentWillReceiveProps');
    }

    shouldComponentUpdate() {
        console.log('Page: shouldComponentUpdate');
        return true;
    }

    componentWillUpdate() {
        console.log('Page: componentWillUpdate');
    }

    // render

    componentDidUpdate() {
        console.log('Page: componentDidUpdate');
    }
}

ReactDOM.render(
    <Page />,
    document.getElementById('app')
);

解答

1. 日志分析

(1)即使沒有改變state悼瘾,也會(huì)調(diào)用shouldComponentUpdate
this.setState({a:2});(改變了state)和this.setState({a:1});(沒有改變state)日志結(jié)果一樣。

// 當(dāng)前組件和子組件shouldComponentUpdate都為true

Page: componentWillMount
Page: render
    A: componentWillMount
    A: render
    A: componentDidMount
Page: componentDidMount

Page: setState
Page: shouldComponentUpdate ---- true
Page: componentWillUpdate
Page: render
    A: componentWillReceiveProps
    A: shouldComponentUpdate ---- true
    A: componentWillUpdate
    A: render
    A: componentDidUpdate
Page: componentDidUpdate

(2)如果A組件的shouldComponentUpdate返回false
那么A組件的componentWillUpdate render componentDidUpdate就都不執(zhí)行了。

// 子組件shouldComponentUpdate為false

Page: componentWillMount
Page: render
    A: componentWillMount
    A: render
    A: componentDidMount
Page: componentDidMount

Page: setState
Page: shouldComponentUpdate ---- true
Page: componentWillUpdate
Page: render
    A: componentWillReceiveProps
    A: shouldComponentUpdate ---- false
Page: componentDidUpdate

注:這一點(diǎn)只是在當(dāng)前React版本中生效

Currently, if shouldComponentUpdate() returns false, then componentWillUpdate(), render(), and componentDidUpdate() will not be invoked. Note that in the future React may treat shouldComponentUpdate() as a hint rather than a strict directive, and returning false
may still result in a re-rendering of the component.
—— React.Component: shouldComponentUpdate()

(3)如果組件PageshouldComponentUpdate返回false
那么Page組件的componentWillUpdate render componentDidUpdate就都不執(zhí)行了税弃。

// 當(dāng)前組件的shouldComponentUpdate為false

Page: componentWillMount
Page: render
    A: componentWillMount
    A: render
    A: componentDidMount
Page: componentDidMount

Page: setState
Page: shouldComponentUpdate ---- false

注意,A組件的componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate也都不執(zhí)行了凑队。
因?yàn)樵蚬咏M件的componentWillReceiveProps是在父組件render后執(zhí)行的,子組件componentDidUpdate后顽决,父組件才會(huì)componentDidUpdate短条。

2. DOM更新

在調(diào)試工具中查看哪些DOM被重新渲染
(1)打開chrome開發(fā)者工具
(2)按Esc,打開console
(3)點(diǎn)擊console左邊的按鈕才菠,勾選Rendering
(4)勾選Paint Flashing


我們發(fā)現(xiàn)茸时,即使render函數(shù)被調(diào)用,DOM也不是全部更新赋访,而是根據(jù)diff算法來更新可都。

3. 結(jié)論

只要執(zhí)行this.setState缓待,則當(dāng)前組件的shouldComponentUpdate就會(huì)被調(diào)用。

如果當(dāng)前組件的shouldComponentUpdate返回true渠牲,
則子組件的componentWillReceiveProps shouldComponentUpdate將被調(diào)用旋炒,不論子組件的props是否被改變
如果當(dāng)前組件的shouldComponentUpdate返回false签杈,
則子組件的componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate被調(diào)用瘫镇。

如果子組件的shouldComponentUpdate返回true,則調(diào)用componentWillUpdate render答姥,然后通過diff算法更新DOM铣除,最后調(diào)用componentDidUpdate
如果子組件的shouldComponentUpdate返回false鹦付,則子組件的componentWillUpdate render componentDidUpdate都不被調(diào)用尚粘。


參考

React.Component: The Component Lifecycle
Reconciliation: The Diffing Algorithm

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市敲长,隨后出現(xiàn)的幾起案子郎嫁,更是在濱河造成了極大的恐慌,老刑警劉巖祈噪,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泽铛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡辑鲤,警方通過查閱死者的電腦和手機(jī)厚宰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來遂填,“玉大人,你說我怎么就攤上這事澈蝙∠偶幔” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵灯荧,是天一觀的道長(zhǎng)礁击。 經(jīng)常有香客問我,道長(zhǎng)逗载,這世上最難降的妖魔是什么哆窿? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮厉斟,結(jié)果婚禮上挚躯,老公的妹妹穿的比我還像新娘。我一直安慰自己擦秽,他們只是感情好码荔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布漩勤。 她就那樣靜靜地躺著,像睡著了一般缩搅。 火紅的嫁衣襯著肌膚如雪越败。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天硼瓣,我揣著相機(jī)與錄音究飞,去河邊找鬼。 笑死堂鲤,一個(gè)胖子當(dāng)著我的面吹牛亿傅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筑累,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼袱蜡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了慢宗?” 一聲冷哼從身側(cè)響起坪蚁,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎镜沽,沒想到半個(gè)月后敏晤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缅茉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年嘴脾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔬墩。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡译打,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拇颅,到底是詐尸還是另有隱情奏司,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布樟插,位于F島的核電站韵洋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏黄锤。R本人自食惡果不足惜搪缨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸵熟。 院中可真熱鬧副编,春花似錦、人聲如沸流强。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至短纵,卻和暖如春带污,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背香到。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工鱼冀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悠就。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓慎式,卻偏偏與公主長(zhǎng)得像臊岸,于是被迫代替她去往敵國(guó)和親禁筏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子繁涂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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

  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過程中的一些閱讀筆記炸茧,個(gè)人覺得該教程講解深入淺出瑞妇,比目前大...
    leonaxiong閱讀 2,813評(píng)論 1 18
  • 深入JSX date:20170412筆記原文其實(shí)JSX是React.createElement(componen...
    gaoer1938閱讀 8,050評(píng)論 2 35
  • 自己最近的項(xiàng)目是基于react的,于是讀了一遍react的文檔梭冠,做了一些記錄(除了REFERENCE部分還沒開始讀...
    潘逸飛閱讀 3,353評(píng)論 1 10
  • react 基本概念解析 react 的組件聲明周期 react 高階組件辕狰,context, redux 等高級(jí)...
    南航閱讀 1,057評(píng)論 0 1
  • It's a common pattern in React to wrap a component in an ...
    jplyue閱讀 3,259評(píng)論 0 2