在虛擬dom中diff的實現。
分別從3個方面:
3. 在React中的實現
react版本16.13.1
必要性分析
呼叫 React 的 render() 方法,會建立一棵由 React 元素組成的樹。 在下一次 state 或 props 更新時, render() 方法會返回一棵不同的樹。 React 需要基於這兩棵樹之間的差別來判斷如何有效率的更新 UI 以保證當前 UI 與最新的樹保持同步。
執行方式
react對tree diff,component diff,element diff進行演算法優化。 React對Virtual DOM樹進行層級控制,只會對相同層級的DOM節點進行比較,即同一個父元素下的所有子節點。 React通過相同類生成相似樹形結構,不同類生成不同樹形結構的策略,對 component diff 進行演算法優化。 React 通過設定唯一 key的策略,對 element diff 進行演算法優化。
協調
當對比兩顆樹時,React 首先比較兩棵樹的根節點,不同型別的根節點元素會有不同的行為
reconcileChildrenArray函式進行協調
reconcileChildrenArray的第二個迴圈的用作:生成fiber連結串列的結構
fiber是一個物件,很多個fiber組合成一個連結串列結構,我們可以通過sibling拿到兄弟節點,通過return拿到父節點。通過effectTag標記在更新DOM時做新增、刪除還是更新操作。
上圖表示一個父節點下面有三個子節點。父節點可以通過child拿到它的第一個子元素,它不能直接拿到它的除了第一個子元素的其他元素,只能通過第一個子元素的sibling拿到。然後每一個子元素都有一個return可以拿到他的父元素。reconcileChildrenArray的第二個迴圈的用作就是生成fiber連結串列結構。
reconcileChildrenArray的第一個迴圈的用作:相對位置沒有變化的更新
更新的時候,遍歷newChildren,並與oldFiber的在真實DOM中下標index位置做比較,如果新元素向前移動了,跳出迴圈,否則,則繼續。計算newFiber,為空跳出迴圈。
reconcileChildrenArray的第三個迴圈的用作:相對位置發生變化的更新
位置發生移動的更新,是將剩下的oldFiber做一個map的key值或者下標對映,遍歷剩下的新陣列,根據map的key值或下標,查詢newFiber。