簡體   English   中英

React 的 Virtual DOM 到底有多快?

[英]How exactly is React's Virtual DOM faster?

我知道 React 的虛擬 DOM 有兩個 arguments 更快 -

  1. 它只更新那些實際需要更新的元素(使用差異)。

  2. 它批量更新,因此我們只更新一次真實的 DOM。 因此,重繪也只進行一次,否則將進行多次。

我對這兩點都有疑問-

  1. 據我所知,所有現代瀏覽器都足夠高效,只更新 DOM 中所需的元素。 例如,如果我有兩個“p”標簽,並且我通過單擊按鈕更改了其中一個 p 標簽中的文本,那么 safari 只會更新該 p 標簽(我已經使用油漆閃爍驗證了這一點)。 那么如果第 1 點已經被瀏覽器實現了,那么它有什么優勢呢?

  2. React 究竟是如何批處理更新的? 最終 React 還必須使用 DOM api 來更新真實的 DOM。 那么為什么如果我們直接使用 DOM api 那么更改不會被批處理,而當 React 使用它時它們會被批處理?

我找到了我的問題的答案。

關鍵是要了解 Virtual DOM 的用途。

首先我們必須看看 React 采用什么方法來渲染組件。

不同的 javascript 框架采用不同的方法來檢測數據 model 的變化並將它們呈現在視圖上。

考慮 AngularJS。 當我們在 Angular 模板中引用我們的數據時,例如在像 {{foo.x}} 這樣的表達式中,Angular 不僅會呈現該數據,還會為該特定值創建一個觀察者。 每當我們的應用程序發生任何事情(點擊事件、HTTP 響應、超時)時,所有的觀察者都會運行。 如果觀察者中的值已更改,則該值將在 UI 中重新呈現。 通過運行所有觀察者 AngularJS 本質上是找出它需要在哪里進行更改。 運行這些觀察者的過程稱為臟檢查。

React 采用了不同的方法。 每當 React 組件中發生 state 更改時,React 不會找出在哪里進行更改(如 AngularJS),而是從頭開始重新渲染整個 UI(具有更新的狀態)。

但是 React 的這種方法有一個問題。 重新渲染整個 UI 意味着重新渲染整個 DOM 樹。 這是一個問題,因為 DOM 更新是一個緩慢的過程(由於回流和重繪)。

這就是 React 的虛擬 DOM 的用武之地。虛擬 DOM 只是 javascript 對象形式的真實 DOM 的表示。 它只是存在於 memory 中的普通 javascript 對象的樹數據結構。 與 Real DOM 相比,Virtual DOM 的渲染要快得多,因為它永遠不會在屏幕上渲染(不需要進行回流或重新繪制)。

那么 Virtual DOM 是如何解決這個問題的呢? 當我們加載我們的應用程序時,React 會創建一個虛擬 DOM,它是真實 DOM 的精確虛擬副本。 每當組件中發生 state 更改時,React 不會重新渲染整個 Real DOM,而是渲染一個全新的 Virtual DOM(具有更新的狀態)。 然后它在舊的虛擬 DOM(真實 DOM 的初始副本)和這個新的虛擬 DOM(在 state 更改后呈現)之間進行比較,以找出它們之間的變化,它只做真實 DOM 中的那些變化。 通過這種方式,整個 UI 被重新渲染(通過渲染一個全新的 Virtual DOM),但只在 Real DOM 中完成了所需的最少更改。

因此,當說“使用 Virtual DOM React 只更新那些需要更新的元素”(我的問題中的第 1 點)時,這意味着在 Virtual DOM React 的幫助下,它正在克服其自身方法的局限性(方法從頭開始渲染整個 UI)。

這個答案也解釋了同樣的概念。

I have seen some answers that state that DOM manipulation using React is faster than using the DOM api because the DOM api re-renders the entire DOM tree whereas React re-renders only those parts of the DOM tree that need to be changed. 這不是真的。 所有現代瀏覽器都足夠高效,只更新 DOM 樹中需要更改的部分。 這可以使用瀏覽器的開發人員工具中的繪畫閃爍來驗證(另請參閱此答案和此答案)。 即使我們假設 DOM api 確實重新渲染了整個 DOM 樹,但這個推理仍然是錯誤的,因為 React 本身的內部代碼必須使用 DOM api 來更新 DOM。 如果 DOM api 確實重新渲染了整個 DOM 樹,那么 React 也會重新渲染整個 DOM 樹,因為最終它也使用 DOM api 來更新 DOM。


至於第二點,React 實際上讓我們更容易進行批處理。

在 React 中,雖然讀取是在 Real DOM 上完成的,但寫入(狀態更改)不是在 Real DOM 上完成的。 相反,寫入是排隊的。 然后當我們所有的讀寫都處理完后,一個新的 Virtual DOM 就會基於這些寫來構建。 然后在新舊 Virtual DOM 之間進行差異化,然后 React 將所需的更改寫入 Real DOM 以更新它。 因此,最終在 Real DOM 上的所有寫入都在一次回流中一起完成。

但是我們也可以在沒有 React 的情況下手動編寫代碼,首先完成所有讀取,然后完成所有寫入。 React 使批處理更容易,因為使用 React 我們不必關心一起進行讀取和寫入,React 會自動為我們批處理寫入。 所以 React 不會讓事情變得很快。 它使事情變得更容易。


總之,我們可以說 React 實際上並不快。 這更容易。 As Pete Hunt says in this video , "React is not magic. Just like you can drop into assembler with C and beat the C compiler, you can drop into raw DOM operations and DOM API calls and beat React if you wanted to. However, using C or Java or JavaScript is an order of magnitude performance improvement because you don't have to worry...about the specifics of the platform. With React you can build applications without even thinking about performance and the default state is fast." .

Rich Harris 的這篇文章還指出,“Virtual DOM 很快”是一個神話。

在此處輸入圖像描述

一旦 React 知道哪些虛擬 DOM 對象發生了變化,那么 React 只會更新真實 DOM 中的那些對象。 與直接操作真實 DOM 相比,這使得性能要好得多。 這使得 React 作為高性能 JavaScript 庫脫穎而出。

關於批量更新:

React 遵循批量更新機制來更新真實的 DOM。 因此,導致性能提高。 這意味着對真實 DOM 的更新是分批發送的,而不是為 state 中的每個更改發送更新。

UI 的重繪是最昂貴的部分,React 有效地確保真正的 DOM 只接收批量更新來重繪 UI。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM