虛擬DOM合理性
由於操作DOM很慢,界面性能很多都是操作DOM引起的,而操作JS很快,用JavaScript對象很容易表示DOM節點,包括標籤屬性子節點,即根據DOM結構遞歸創建虛擬DOM樹,在頁面狀態改變需要操作DOM時,先通過虛擬DOM計算出對真實DOM的最小修改量,然後再修改真實的DOM。
- 1.兩個相同組件產生類似的結構,不同組件產生不同的DOM結構。
- 2.對於同一層次的一組子節點,通過唯一的key值進行區分。
一、不同節點類型的比較
- 在虛擬樹中比較兩個虛擬DOM節點,若兩個節點類型不同,則直接銷燬前面的節點,創建並插入新節點。
- 若被刪除的節點之下還有子節點,那麼這些子節點也會一併刪除。因爲一般情況不同組件產生不同的DOM結構,與其浪費時間比較他們基本不會相等的DOM結構還不如加個新組建上去。
二、只會逐層比較節點
比如A節點下有子節點BC,要將A節點包括其子節點移動到其他節點下面,則不是將A賦值並移動到其他節點如D下面,而是重新創建每一個節點:
A.destroy();
A = new A();
a.append(new B());
a.append(new C());
D.append(A);
三、相同節點類型的比較
相同類型的節點, 對屬性進行重設。
四、列表節點的比較
列表中節點若沒有唯一標識的key值的話,會提示警告。
假設在列表ABCD中B的後面插入E,若沒有key值則會將C更新爲E,將D更新爲C,最後插入D節點。
但是若有key值的話,react會找到正確的插入位置。
還有若A下面有BC子節點,若未提供key值,則react認爲BC類型不同,要調整BC的位置會將BC刪除後重新新建再插入,若有key值的話,則只是更新BC和其父組件而已。
diff
算法
diff
算法採用動態規劃的方法求兩個序列X和Y
,長度分別爲m,n,
的最長公共子序列,時間複雜度爲mn,
比較兩顆樹的時間複雜度爲n^3
,因爲樹遍歷複雜度爲n
:
假設有兩個序列X=(GAC),
長度爲m,Y=(AGCAT),
長度爲n
,則X和Y的嘴饞公共子序列爲:
最長公共子序列LCS(Xi,Yj)
分析:
- 當
X
或者Y
中有一個長度爲0時,其公共子序列爲空; - 當
X
和Y
的第i
個字符相等時,其公共子序列LCS(Xi,Yj)
=Xi
並LCS(Xi-1,Yj-1)
; - 當
X
和Y
的第i
個字符不相等時,其公共子序列LCS(Xi,Yj)
爲LCS(Xi,Yj-1)
和LCS(Xi-1,Yj)
中最大的一個。
由於第i
次構造最長公共子序列時要用到第i-1
次的最長公共子序列,因此將第一次構造時的最長公共子序列設爲空;
舉例:
最後一個格子,
C
和T
不等,因此,取LCS('GAC','AGCA')=倒數第一行倒數第二個格子
和LCS('GA','AGCAT')=倒數第一列倒數第二個格子
的最大值,即(AC)&(GC)&(GA)
;第4行的
A
和第6列的A
相等時取A
並LCS('G','AGC')=G
.