最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React Diff原理深入分析

 更新時間: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時的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")
);

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

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

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

1.兩個不同類型的元素會產(chǎn)生出不同的樹;

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

Diffing 算法

逐層比較

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

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

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

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

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

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

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

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

對比同類型的組件元素

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

對比同一類型的元素

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

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

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

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

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

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

所以在列表末尾新增元素時,更新開銷比較小。例如:

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

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

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

如果只是簡單的將新增元素插入到表頭,那么更新開銷會比較大。比如:

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

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

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

Keys

為了解決上述問題,React 引入了 key 屬性。當(dāng)子元素?fù)碛?key 時,React 使用 key 來匹配原有樹上的子元素以及最新樹上的子元素。以下示例在新增 key 之后,使得樹的轉(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 的元素僅僅移動了。所以只是創(chuàng)建了 key=2014的元素,并不會創(chuàng)建剩下的兩個元素。

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

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

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

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

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

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

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

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

相關(guān)文章

  • react分頁顯示數(shù)據(jù)的方法

    react分頁顯示數(shù)據(jù)的方法

    分頁在很多地方都可以用到,本文主要實現(xiàn)了react分頁顯示,主要使用三個組件,父組件listBox、列表組件List、按鈕組件PageButton,感興趣的可以了解一下
    2021-08-08
  • React hooks異步操作踩坑記錄

    React hooks異步操作踩坑記錄

    這篇文章主要介紹了React hooks異步操作踩坑記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • React-Native之TextInput組件的設(shè)置以及如何獲取輸入框的內(nèi)容

    React-Native之TextInput組件的設(shè)置以及如何獲取輸入框的內(nèi)容

    這篇文章主要介紹了React-Native之TextInput組件的設(shè)置以及如何獲取輸入框的內(nèi)容問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 如何創(chuàng)建自己的第一個React 頁面

    如何創(chuàng)建自己的第一個React 頁面

    React是用于構(gòu)建用戶界面的JavaScript庫,本文主要介紹了如何創(chuàng)建自己的第一個React頁面,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • react native仿微信PopupWindow效果的實例代碼

    react native仿微信PopupWindow效果的實例代碼

    本篇文章主要介紹了react native仿微信PopupWindow效果的實例代碼,具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • 使用react-activation實現(xiàn)keepAlive支持返回傳參

    使用react-activation實現(xiàn)keepAlive支持返回傳參

    本文主要介紹了使用react-activation實現(xiàn)keepAlive支持返回傳參,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • React前端DOM常見Hook封裝示例上

    React前端DOM常見Hook封裝示例上

    這篇文章主要為大家介紹了React前端DOM常見Hook封裝示例上篇,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • React-Native中禁用Navigator手勢返回的示例代碼

    React-Native中禁用Navigator手勢返回的示例代碼

    本篇文章主要介紹了React-Native中禁用Navigator手勢返回的示例代碼,具有一定的參考價值,有興趣的可以了解一下
    2017-09-09
  • 使用react完成點(diǎn)擊返回頂部操作

    使用react完成點(diǎn)擊返回頂部操作

    本文主要介紹了使用react完成點(diǎn)擊返回頂部操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • ReactDOM.render在react源碼中執(zhí)行原理

    ReactDOM.render在react源碼中執(zhí)行原理

    這篇文章主要為大家介紹了ReactDOM.render在react源碼中執(zhí)行原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12

最新評論

邻水| 沂南县| 法库县| 凤凰县| 宜川县| 龙海市| 耒阳市| 郴州市| 桐梓县| 司法| 贡觉县| 土默特右旗| 郯城县| 连平县| 南投市| 西充县| 盖州市| 台东市| 潼关县| 天长市| 绥阳县| 且末县| 洪泽县| 米林县| 南宁市| 贡觉县| 水城县| 蒲江县| 荣昌县| 成都市| 望城县| 宝丰县| 涡阳县| 剑川县| 育儿| 两当县| 乌兰县| 阳高县| 鹤岗市| 攀枝花市| 石泉县|