深入 React 之 diff 演算法

2021-10-03 02:34:47 字數 1557 閱讀 1381

寫前端的人都知道 react 框架採用的是虛擬 dom。而虛擬 dom 就是 js 物件到真實 dom 的一種對映。

'list'

>

='item'

>item 1

<

/li>

<

/ul>

, children:

[, children:

["item 1"]}

,]}

從上述案例中可以看到,真實 dom 對映出來的 js 物件(虛擬 dom)是一種樹形結構。其中 tagname 是 string 型別,節點的標籤名稱。props 是 object 型別,節點的屬性集,包括 id,class 等。children 則是 array 型別,包含節點的子節點。某個節點的文字內容也是其子節點。譬如item 1就是li節點的子節點。

注:本文提到的元件、節點、元素都可以理解為 dom 節點。

在使用 setstate 方法更新元件的時候,新舊元件會進行對比。這個對比的過程也就是 diff 演算法。對比之後再對區域性差異部分進行更新。這就是 diff 演算法的簡易過程。

diff 演算法的作用就是尋找兩個虛擬 dom 節點的差異,而這個虛擬 dom,其實就是兩個 js 物件,因為節點是層層巢狀的,所以這兩個 js 物件會呈樹形結構,而 diff 演算法就是計算出兩個樹形結構的物件的差異部分,並只針對該部分修改原生節點。而不是重新渲染整個頁面,以此來提高頁面內容更新速度。

採用兩個元件遞迴的方式。時間複雜度為 o(n^3)。其中 n 為子節點數。也就是如果有 100 個節點。需要執行 1000000 次。

react diff 演算法是對樹的每一層進行遍歷,如果節點沒有就刪除節點。對於不同型別的節點,直接替換。對於相同型別的節點,使用 shouldcomponentupdate 進行判斷。react 中採用三大策略將時間複雜度為 o(n^3)優化到 o(n)。

跨層級的 dom 操作忽略不計。

擁有相同型別的元件節點生成相似的樹形結構,擁有不用型別的元件節點生成不同的樹形結構。

對於同一層級的節點,用唯一 id 區別。

在元件更新的時候執行。

尋找差異,區域性更新。

以上說到 diff 演算法的核心就是元件更新。元件型別分為三種,分別為文字元素、自定義元素和 dom元素。

文字元素更新:直接更新替換文字,不會呼叫 diff 演算法。

自定義元素更新:同型別的元素,繼續比較下去。不同型別的元素直接替換。

dom 元素更新:對於屬性差異部分,直接更新屬性,對於子節點屬性差異部分,直接改變子節點屬性。對子節點更新,找出節點的差異,更新差異部分的 dom 元素。

當 dom 跨層級操作時,只會刪除或建立節點。因此有可能整個節點樹都會被重新建立。所以盡量不要跨層級新增或移除操作,可以通過 css 顯示/隱藏節點。

使用 shouldcomponentupdate() 來減少元件不必要的更新。

開發元件時保持 dom 結構的穩定性,盡量不要動態操作 dom,尤其是移動 dom。

盡量避免將最後乙個列表節點移動到首位的操作。

React的Diff演算法

要掌握react的diff演算法我們必須先了解一下其渲染的機制 在每一次的狀態或者屬性更新的時候,react元件的render方法會進行渲染,返回乙個虛擬dom物件,這個就是react的渲染機制。但是這裡就有個問題,每次生成新的dom結構,也還是要轉化為真實的dom,還是會帶來大量的真實dom的操作...

React的diff演算法

react的diff演算法主要是兩個tree的比較。傳統的tree diff演算法複雜度是o n 3 react是演算法通過一些策略將複雜度將為o n 1.優化策略 1.網頁中的dom跨層級移動的特別少,可以忽略不計 2.相同型別的元件生成相似的樹形結構,不同型別的元件生成不同的樹形結構 3.同一層...

React篇之 虛擬DOM和DIFF演算法

什麼是虛擬dom?使用js物件模擬出dom樹中的元素和元素巢狀的關係,從而實現頁面元素的高效更新.例如123123 對應的js物件就長這樣 var vdom children children 123123 這個vdom就是乙個虛擬dom 虛擬dom相比於真實dom的優勢在 真實的dom在進行資料改...