亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

React Diff原理深入分析

 更新時(shí)間:2021年04月22日 09:44:45   作者:AkeAke  
這篇文章主要介紹了React Diff原理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下

在了解Diff前,先看下React的虛擬DOM的結(jié)構(gòu)

這是html結(jié)構(gòu)

<div id="father">
  <p class="child">I am child p</p>
  <div class="child">I am child div</div>
</div>

這是React渲染html時(shí)的js代碼   自己可以在babel上試試

React.createElement("div", {id: "father"}, 
    React.createElement("p", {class: "child"}, "I am child p"),             
    React.createElement("div", {class: "child"}, "I am child div")
);

由此可以看出這是一個(gè)樹(shù)結(jié)構(gòu)

React在調(diào)用render方法時(shí)會(huì)創(chuàng)建一顆樹(shù)(簡(jiǎn)稱pre),在下一次調(diào)用render方法時(shí)會(huì)返回一顆不同的樹(shù)(簡(jiǎn)稱cur)。React就會(huì)比較pre和cur這兩棵樹(shù)之間的差別來(lái)判斷如何高效的更新UI,保證當(dāng)前UI與最新的樹(shù)cur保持同步。

為了高效更新UI,React在以下兩個(gè)假設(shè)的基礎(chǔ)上提出了一套O(n)的啟發(fā)算法:

1.兩個(gè)不同類型的元素會(huì)產(chǎn)生出不同的樹(shù);

2.開(kāi)發(fā)者可以通過(guò)設(shè)置 key 屬性,來(lái)告知渲染哪些子元素在不同的渲染下可以保存不變;

Diffing 算法

逐層比較

在對(duì)比兩棵樹(shù)時(shí),React是逐層進(jìn)行比較的,只會(huì)對(duì)相同顏色框內(nèi)的DOM節(jié)點(diǎn)進(jìn)行比較。

首先比較兩棵樹(shù)的根節(jié)點(diǎn),不同類型的根節(jié)點(diǎn)會(huì)有不同的形態(tài)。當(dāng)根節(jié)點(diǎn)為不同類型的元素時(shí),React 會(huì)拆卸原有的樹(shù)并且建立起新的樹(shù)。舉個(gè)例子,當(dāng)一個(gè)元素從 <a> 變成 <img>,從 <Article> 變成 <Comment>,或從 <Button> 變成 <div> 都會(huì)觸發(fā)一個(gè)完整的重建流程。

//before
<div>
    <App/>
</div>
//after
<p>
    <App/>
</p>

React會(huì)銷毀App組件(該組件的子組件也全都銷毀),并且重新創(chuàng)建一個(gè)新的App組件(也包括App的子組件)。

如下的DOM結(jié)構(gòu)轉(zhuǎn)換:

React只會(huì)簡(jiǎn)單的考慮同層節(jié)點(diǎn)的位置變換,對(duì)于不同層的節(jié)點(diǎn),只有簡(jiǎn)單的創(chuàng)建和刪除。當(dāng)根節(jié)點(diǎn)發(fā)現(xiàn)子節(jié)點(diǎn)中A不見(jiàn)了,就會(huì)直接銷毀A;而當(dāng)D發(fā)現(xiàn)自己多了一個(gè)子節(jié)點(diǎn)A,則會(huì)創(chuàng)建一個(gè)新的A作為子節(jié)點(diǎn)。因此對(duì)于這種結(jié)構(gòu)的轉(zhuǎn)變的實(shí)際操作是:

A.destroy();
A = new A();
A.append(new B());
A.append(new C());
D.append(A);

雖然看上去這樣的算法有些“簡(jiǎn)陋”,但是其基于的是第一個(gè)假設(shè):兩個(gè)不同類型的元素會(huì)產(chǎn)生出不同的樹(shù)。根據(jù)React官方文檔,這一假設(shè)至今為止沒(méi)有導(dǎo)致嚴(yán)重的性能問(wèn)題。這當(dāng)然也給我們一個(gè)提示,在實(shí)現(xiàn)自己的組件時(shí),保持穩(wěn)定的DOM結(jié)構(gòu)會(huì)有助于性能的提升。例如,我們有時(shí)可以通過(guò)CSS隱藏或顯示某些節(jié)點(diǎn),而不是真的移除或添加DOM節(jié)點(diǎn)。

對(duì)比同類型的組件元素

當(dāng)一個(gè)組件更新時(shí),組件實(shí)例會(huì)保持不變,但是state或props中數(shù)據(jù)的變化會(huì)調(diào)用render從而改變?cè)摻M件中的子元素進(jìn)行更新。 

對(duì)比同一類型的元素

當(dāng)對(duì)比兩個(gè)相同類型的 React 元素時(shí),React 會(huì)保留 DOM 節(jié)點(diǎn),僅比對(duì)及更新有改變的屬性。

<div className="before" title="stuff" />

<div className="after" title="stuff" />

React將div的className由before修改為after(類似于React中更新state的合并操作)。

對(duì)子節(jié)點(diǎn)進(jìn)行遞歸

默認(rèn)情況下(逐層比較),當(dāng)遞歸 DOM 節(jié)點(diǎn)的子元素時(shí),React 會(huì)同時(shí)遍歷兩個(gè)子元素的列表;當(dāng)產(chǎn)生差異時(shí),生成一個(gè) mutation(突變)。

所以在列表末尾新增元素時(shí),更新開(kāi)銷比較小。例如:

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React 會(huì)先匹配兩個(gè) <li>first</li> 對(duì)應(yīng)的樹(shù),然后匹配第二個(gè)元素 <li>second</li> 對(duì)應(yīng)的樹(shù),最后插入第三個(gè)元素的 <li>third</li> 樹(shù)。

如果只是簡(jiǎn)單的將新增元素插入到表頭,那么更新開(kāi)銷會(huì)比較大。比如:

<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

React 并不會(huì)意識(shí)到應(yīng)該保留 <li>Duke</li> 和 <li>Villanova</li>,而是會(huì)重建每一個(gè)子元素。這種情況會(huì)帶來(lái)性能問(wèn)題。

Keys

為了解決上述問(wèn)題,React 引入了 key 屬性。當(dāng)子元素?fù)碛?key 時(shí),React 使用 key 來(lái)匹配原有樹(shù)上的子元素以及最新樹(shù)上的子元素。以下示例在新增 key 之后,使得樹(shù)的轉(zhuǎn)換效率得以提高:

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

現(xiàn)在 React 知道只有帶著 '2014' key 的元素是新元素,帶著 '2015' 以及 '2016' key 的元素僅僅移動(dòng)了。所以只是創(chuàng)建了 key=2014的元素,并不會(huì)創(chuàng)建剩下的兩個(gè)元素。

所以key的取值最好不要使用數(shù)組的下標(biāo),因?yàn)閿?shù)組的順序可能會(huì)發(fā)生變化,最好使用自身數(shù)據(jù)攜帶的唯一標(biāo)識(shí)(id或是其它的屬性)。

1. 虛擬DOM中key的作用:
                    1). 簡(jiǎn)單的說(shuō): key是虛擬DOM對(duì)象的標(biāo)識(shí), 在更新顯示時(shí)key起著極其重要的作用。

                    2). 詳細(xì)的說(shuō): 當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí),react會(huì)根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】,  隨后React進(jìn)行【新虛擬DOM】與【舊虛擬DOM】的diff比較,比較規(guī)則如下:

                                    a. 舊虛擬DOM中找到了與新虛擬DOM相同的key:
                                                (1).若虛擬DOM中內(nèi)容沒(méi)變, 直接使用之前的真實(shí)DOM
                                                (2).若虛擬DOM中內(nèi)容變了, 則生成新的真實(shí)DOM,隨后替換掉頁(yè)面中之前的真實(shí)DOM

                                    b. 舊虛擬DOM中未找到與新虛擬DOM相同的key
                                                根據(jù)數(shù)據(jù)創(chuàng)建新的真實(shí)DOM,隨后渲染到到頁(yè)面

2. 用index作為key可能會(huì)引發(fā)的問(wèn)題:
                                1. 若對(duì)數(shù)據(jù)進(jìn)行:逆序添加、逆序刪除等破壞順序操作:
                                                會(huì)產(chǎn)生沒(méi)有必要的真實(shí)DOM更新 ==> 界面效果沒(méi)問(wèn)題, 但效率低。

                                2. 如果結(jié)構(gòu)中還包含輸入類的DOM:
                                                會(huì)產(chǎn)生錯(cuò)誤DOM更新 ==> 界面有問(wèn)題。                                                
                                3. 注意!如果不存在對(duì)數(shù)據(jù)的逆序添加、逆序刪除等破壞順序操作,
                                        僅用于渲染列表用于展示,使用index作為key是沒(méi)有問(wèn)題的。

以上就是React Diff原理深入分析的詳細(xì)內(nèi)容,更多關(guān)于React Diff原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React自定義視頻全屏按鈕實(shí)現(xiàn)全屏功能

    React自定義視頻全屏按鈕實(shí)現(xiàn)全屏功能

    這篇文章主要介紹了React自定義視頻全屏按鈕實(shí)現(xiàn)全屏功能,通過(guò)繪制全屏按鈕,并綁定點(diǎn)擊事件,編寫(xiě)點(diǎn)擊事件,通過(guò)實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下
    2022-11-11
  • 基于React實(shí)現(xiàn)搜索GitHub用戶功能

    基于React實(shí)現(xiàn)搜索GitHub用戶功能

    在本篇博客中,我們將介紹如何在 React 應(yīng)用中搜索 GitHub 用戶并顯示他們的信息,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • 2個(gè)奇怪的react寫(xiě)法

    2個(gè)奇怪的react寫(xiě)法

    大家好,我卡頌。雖然React官網(wǎng)用大量篇幅介紹最佳實(shí)踐,但因JSX語(yǔ)法的靈活性,所以總是會(huì)出現(xiàn)奇奇怪怪的React寫(xiě)法。本文介紹2種奇怪(但在某些場(chǎng)景下有意義)的React寫(xiě)法。也歡迎大家在評(píng)論區(qū)討論你遇到過(guò)的奇怪寫(xiě)法
    2023-03-03
  • 詳解開(kāi)發(fā)react應(yīng)用最好用的腳手架 create-react-app

    詳解開(kāi)發(fā)react應(yīng)用最好用的腳手架 create-react-app

    本篇文章主要介紹了詳解開(kāi)發(fā)react應(yīng)用最好用的腳手架 create-react-app,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • 詳解react組件通訊方式(多種)

    詳解react組件通訊方式(多種)

    這篇文章主要介紹了詳解react組件通訊方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • React虛擬列表的實(shí)現(xiàn)代碼

    React虛擬列表的實(shí)現(xiàn)代碼

    最近看了vueuse的useVirtualList的實(shí)現(xiàn)方式,發(fā)現(xiàn)虛擬滾動(dòng)效果不錯(cuò),就嘗試著同樣的寫(xiě)法改成react版本,虛擬列表主要包含三部分組成,offset,viewcapacity,overscan,本文就給大家介紹一下React虛擬列表的實(shí)現(xiàn),需要的朋友可以參考下
    2023-08-08
  • react koa rematch 如何打造一套服務(wù)端渲染架子

    react koa rematch 如何打造一套服務(wù)端渲染架子

    這篇文章主要介紹了react koa rematch 如何打造一套服務(wù)端渲染架子,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題

    使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題

    使用redux管理數(shù)據(jù),由于Store獨(dú)立于組件,使得數(shù)據(jù)管理獨(dú)立于組件,解決了組件之間傳遞數(shù)據(jù)困難的問(wèn)題,非常好用,今天重點(diǎn)給大家介紹使用react+redux實(shí)現(xiàn)計(jì)數(shù)器功能及遇到問(wèn)題,感興趣的朋友參考下吧
    2021-06-06
  • 基于Webpack4和React hooks搭建項(xiàng)目的方法

    基于Webpack4和React hooks搭建項(xiàng)目的方法

    這篇文章主要介紹了基于Webpack4和React hooks搭建項(xiàng)目的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • 基于visual studio code + react 開(kāi)發(fā)環(huán)境搭建過(guò)程

    基于visual studio code + react 開(kāi)發(fā)環(huán)境搭建過(guò)程

    今天通過(guò)本文給大家分享基于visual studio code + react 開(kāi)發(fā)環(huán)境搭建過(guò)程,本文給大家介紹的非常詳細(xì),包括react安裝問(wèn)題及安裝 Debugger for Chrome的方法,需要的朋友跟隨小編一起看看吧
    2021-07-07

最新評(píng)論