1. diff算法
React組件的核心思想是:
- 將頁面拆分為一個個組件崖堤,一個組件還可能嵌套更小的組件吗氏,每個組件都有自己的數(shù)據幅垮,當某個組件的數(shù)據發(fā)生變化時乌昔,更新該組件的部分視圖隙疚。
- 更新的過程是由數(shù)據驅動的,新的數(shù)據自該組件頂層向下流向子組件磕道,每個組件調用自己的render方法得到新的視圖供屉,并與之前的視圖diff比較差異,完成更新,這個過程就是reconciliation-調和
虛擬DOM基本原理:
用純js對象來模擬DOM樹伶丐,每當更新時悼做,根據組件的render方法計算出新的虛擬DOM樹,并與之前的虛擬DOM樹作比較撵割,得到一個差異補丁贿堰,最后隱射到真正的DOM樹上完成視圖更新辙芍,以減少操作DOM的次數(shù)
diff算法:前端很少跨越層級移動DOM元素啡彬,只會對虛擬DOM中同一層級的元素進行比較,這樣算法復雜度就可以達到O(n)
diff碰到列表會有問題
發(fā)現(xiàn)列表元素不同時故硅,就會對其進行重渲染庶灿,但是可能只是進行了插入操作,只需要進行移動操作即可吃衅,需要定義key屬性往踢,diff時就會去查找是否有相同的key元素,比較它們是否完全相同徘层,若是則會復用該元素峻呕,免去不必要的操作
不推薦使用數(shù)組的index作為key,因為如果數(shù)據重排趣效,index并不能起到唯一標識的作用瘦癌,每次視圖元素都會重新渲染
diff會幫我們計算出虛擬DOM中真正變化的部分,并只針對該部分進行原生DOM操作跷敬,而非重新渲染整個頁面讯私,從而保證了每次操作更新后頁面的高效渲染
傳統(tǒng)diff算法循環(huán)遞歸對節(jié)點進行依次比較,算法復雜度為O(n3)西傀,React可以轉化為O(n)復雜度
2.diff策略
diff算法的三個策略
- DOM節(jié)點的跨層級的移動操作特別少斤寇,可以忽略不計
- 擁有相同類的兩個組件會生成相似的樹形結構,擁有不同類的兩個組件會生成不同的樹形結構
- 對于同一層級的一組子節(jié)點拥褂,它們可以通過唯一id進行區(qū)分
2.1 tree diff
對樹進行分層比較娘锁,兩棵樹只會對同一層次的節(jié)點進行比較,即同一個父節(jié)點下的所有子節(jié)點饺鹃,當發(fā)現(xiàn)節(jié)點已經不存在時致盟,則該節(jié)點及其子節(jié)點會被完全刪除掉,不會用于進一步的比較尤慰,這樣只需要對樹進行一次遍歷
當出現(xiàn)節(jié)點跨層級移動時馏锡,并不會出現(xiàn)想象中的移動操作,而是移除不存在的節(jié)點及其子節(jié)點伟端,創(chuàng)建存在的節(jié)點
注意:在開發(fā)組件時杯道,保持穩(wěn)定的DOM結構會有助于性能的提升,可以通過CSS隱藏或顯示節(jié)點,而不是真正移除或添加DOM節(jié)點
2.2 component diff
組件間比較:
- 同一類型組件党巾,按照原策略繼續(xù)比較虛擬DOM樹
- 將該組件判斷為dirty component萎庭,替換整個組件下的所有子節(jié)點
- 同一類型組件,可能虛擬DOM完全沒有變化齿拂,用戶通過shouldComponentUpdate來判斷組件是否需要進行diff算法
即不同組件則驳规,直接替換掉組件下的所有子節(jié)點