1. 程式人生 > >【React自制全家桶】二、分析React的虛擬DOM和Diff演算法

【React自制全家桶】二、分析React的虛擬DOM和Diff演算法

一、React如何更新DOM內容:

1.  獲取state 資料

2.  獲取JSX模版


3.  通過資料 +模版結合,生成真實的DOM, 來顯示,以下行程式碼為例(簡稱程式碼1) 

1 <div id=' abc '><span>hello world</ span></div>

4.生成程式碼1對應的虛擬DOM (簡稱程式碼2):(解釋:虛擬DOM就是一個JS物件,用它來描述真實DOM)

['div', {id: 'abc'}, ['span',  {},  'hello world' ] ]

5.  當state  發生變化

6.生成新的虛擬DOM(簡稱程式碼3)

['div', {id:  ' abc' },  ['span',  {},  'bye bye']]

7.比較原始虛擬DOM和新的虛擬DOM的區別(即比較程式碼2和程式碼3),找到兩者區別是Span中內容.  直接操作DOM,改變span中的內容

二、React如何提高效能了

而傳統處理方式是:先改變資料後生成DOM物件,然後讓兩個DOM物件做對比。

都知道,只要是對DOM直接操作,不管是生成DOM還是對比DOM都是非常耗效能的。

而React的底層上述已經介紹了,生成的是虛擬DOM,本質就是生成JS物件,這個耗能是非常低的。

所以,React能極大的提升效能

三、Diff演算法核心(Diff演算法即新舊虛擬DOM比較演算法)

1.在哪用到了Diff演算法

首先Diff演算法在React的虛擬DOM中的第7步涉及:

即比較原始虛擬DOM和新的虛擬DOM的區別(即比較程式碼1和程式碼3)

2.Diff演算法核心之合併setState

如圖:當在很短的時間內有多個setState發生時,則Diff演算法會自動將其合併為一個時間,從而只比對一次,提高效能

3.Diff演算法核心之同層比較

資料改變重新比對虛擬DOM時,新虛擬DOM與舊虛擬DOM進行同層比較,從根節點開始比較,當節點資料發生改變時,該節點和從該節點延展出的所有子節點都將被替換。

可能有人認為這樣比較的話,如果新舊虛擬DOM子節點中有相同的但還是全部被替換,那豈不是造成資源浪費了?確實造成資源浪費啦,但是因為這個演算法非常簡潔所以執行速度很快,因而演算法的綜合效率更高。

4.Diff演算法核心之Key值

Diff演算法當遇到迴圈的陣列時,比對是根據每一項資料的key值來進行比較的,這樣有助於提升效率。

但是建議不要將index值作為key值。因為每項的index值並不是定值。

比如陣列[a,b,c],其中a、b、c對於下標0、1、2,當刪去a時,陣列為[b,c],對於下標為0、1。

顯然b和c的前後index值改變啦,這樣會讓React重新渲染該陣列每一項。導致效能損耗。

建議:最簡單的方法是使用item做key值。