在vue,react這些框架中,都是通過監聽資料的變化而相應的去渲染我們的檢視.但是如果每次修改資料就去操作一次dom樹,這在效能上無疑是大打折扣的.虛擬dom的出現就是為了解決這個問題,並且起到協調的作用.本質上就是在js和真實dom樹之間做了乙個快取,具體原理是:每次當資料發生變化時,渲染機制先在虛擬dom上去改變檢視,然後再跟實際dom樹作比較(作比較用到的是虛擬dom的diff演算法),再在實際dom上更新差異部分(也就是這個時候才去操作實際dom樹,渲染差異部分),這樣就減少了對實際dom樹的操作,達到效能優化的效果.
簡單理解為:虛擬dom樹其實是實際dom樹更改之前的參考物件,是js實際操作dom節點時與真實dom樹之間的乙個中介(快取).以達到減少對dom節點的頻繁無效的操作和效能優化的目的.
兩種方式:
1.純js (一般不用這種)
2.jsx
<
!doctype html>
"en"
>
"utf-8"
>
"viewport" content=
"width=device-width, initial-scale=1.0"
>
"">
<
/script>
"">
<
/script>
<
!-- 由於瀏覽器的js引擎不能直接解析jsx
.需要babel.js轉譯為純js** --
>
"">
<
/script>
react<
/title>
<
/head>
// 建立虛擬dom容器
"myvirt"
>
<
/div>
"myvirt2"
>
<
/div>
"text/babel"
>
// 使用jsx建立虛擬dom時,type不能少
// 純js建立虛擬dom 建立標籤 屬性 文字內容
var str = react.
createelement
('div',,
'js建立虛擬dom');
console.
log(str,
1234
)// 渲染虛擬dom:reactdom.render(virtualdom,containerdom)
reactdom.
render
(str,document.
getelementbyid
("myvirt"))
var text =
"我是jsx虛擬dom"
;var viturldiv =
"myvirt2"
>
<
/div>
// jsx建立虛擬dom
reactdom.
render
(viturldiv,document.
getelementbyid
("myvirt2"))
<
/script>
<
/body>
<
/html>
diff演算法:該演算法並不是react獨有的演算法,react只是在傳統diff演算法的基礎上做了一些優化而已.實現機制是:深度遍歷dom樹,從根節點開始優先查詢節點的左子樹及其左節點,完全遍歷完左子樹之後才會開始去查詢右子樹,查詢右子樹時也是先從右子樹的左節點開始往下查詢,直到遍歷完全.比較出兩棵樹之間的差異,然後在真實dom樹更新差異部分.
diff演算法的比較規則:
節點不存在,直接建立該節點;
節點存在且節點型別相同,繼而判斷屬性是否相同,不同則修改節點屬性,無需刪除該節點
節點存在且節點型別相同,繼而判斷文字內容是否相同,有差異則做出修改.
節點型別不同,直接刪除元素及其子節點,替換成新節點
兩個節點之間的差異包括:
1.直接替換原有節點
2.調整子節點,包括移動刪除等操作
3.修改節點屬性,文字內容
react diff:tree diff component diff element diff
官方建議不要出現跨層級的節點操作,當出現節點跨層級移動時,react並不會去移動節點,而是刪除要移動的節點及其子節點並重新建立到移動位置,
場景假設:
假如我有一千個節點,當我刪除第乙個節點時,那我要去更新剩下的999個節點的位置,針對相同的節點只是位置發生變化就會出現大量的刪除/建立節點的操作,這無疑會影響到react的效能.
*針對這一問題,react diff做出的優化措施是:*對同一層級的同組子節點(也就是父節點下的所有子節點)新增唯一的key來進行區分.
其實針對相同節點的操作,如果我有唯一的key值,我就根據這個key值去定位需要操作的節點,執行刪除操作即可,也不會影響到其他節點.如果要移動節點之間的位置,同理根據key值找到對應的節點,交換位置並更新為新的節點集合即可,其他節點不需要發生任何操作.這樣來達到優化.
key的作用主要是:
1.準確判斷除當前節點是否在舊集合中
2.極大的減少遍歷次數
當然也不是所有都加上key就是效能優化了,對於簡單列表頁渲染來說,不加key要比加了key的效能好.
例如:
>
1div
>
key=
"1">
1>
>
2div
>
key=
"2">
2>
>
3div
>
key=
"3">
3>
>
4div
>
key=
"4">
4>
>
5div
>
key=
"5">
5>
我如果要修改節點2跟4的位置,沒有key值的話我直接修改innertext即可.加了key值之後我需要去找到key=2的節點然後再找到key=4的節點,然後再將兩個節點調換位置.這樣移動dom節點的操作效能上就不如直接修改innertext.
所以,請注意不是加了key就一定優化效能.
參考大佬部落格:
React 虛擬 Dom 和 diff 演算法
react將dom抽象為虛擬dom,然後通過新舊虛擬dom 這兩個物件的差異 diff演算法 最終只把變化的部分重新渲染,提高渲染效率的過程 概念講完再描述一遍 一句話 用 js 物件的形式,來表現一棵真是的 dom 樹 傳統的 diff 演算法也是一直都有的 react 通過制定大膽的策略,將 o...
react 虛擬DOM的diff演算法
1 state 資料 2 jsx模板 3 生成虛擬dom 虛擬dom就是乙個js物件,用它來描述真實dom div span hello world 通過這樣的乙個js物件,我們就可以表述上面的dom結構了 4 用虛擬dom的結構,生成真實的dom,來顯示 abc hello world span ...
react虛擬dom機制與diff演算法
react的乙個突出特點是擁有極速地渲染效能。該功能依靠的就是facebook研發團隊弄出的虛擬dom機制以及其獨特的diff演算法。下面簡單解釋一下react虛擬dom機制和diff演算法的實現思想 要講虛擬dom機制必須提到乙個概念 虛擬dom樹,這是react在真實dom樹基礎上建立的乙個抽象...