簡體   English   中英

為什么說 React 的 Virtual DOM 概念比 dirty model 檢查性能更高?

[英]Why is React's concept of Virtual DOM said to be more performant than dirty model checking?

我在 ( Pete Hunt: React: Rethinking best practices -- JSConf EU 2013 ) 上看到了一個React開發演講,演講者提到 model 的臟檢查可能很慢。 但是計算虛擬 DOM 之間的差異實際上不是更差嗎,因為在大多數情況下,虛擬 DOM 應該大於 model?

我真的很喜歡虛擬 DOM 的潛在力量(尤其是服務器端渲染),但我想知道所有的優缺點。

我是virtual-dom模塊的主要作者,所以我可以回答你的問題。 實際上這里有兩個問題需要解決

  1. 我什么時候重新渲染? 答:當我觀察到數據是臟的。
  2. 如何有效地重新渲染? 答:使用虛擬 DOM 生成真實的 DOM 補丁

在 React 中,你的每個組件都有一個狀態。 這種狀態就像一個可以在淘汰賽或其他 MVVM 風格庫中找到的可觀察對象。 本質上,React 知道何時重新渲染場景,因為它能夠觀察到這些數據何時發生變化。 臟檢查比 observable 慢,因為您必須定期輪詢數據並遞歸檢查數據結構中的所有值。 相比之下,在狀態上設置一個值將向偵聽器發出信號,表明某些狀態已更改,因此 React 可以簡單地偵聽狀態上的更改事件並排隊重新渲染。

虛擬 DOM 用於高效地重新渲染 DOM。 這與臟檢查您的數據並沒有真正的關系。 您可以使用帶有或不帶有臟檢查的虛擬 DOM 重新渲染。 您是對的,因為在計算兩個虛擬樹之間的差異時存在一些開銷,但是虛擬 DOM 差異是關於了解 DOM 中需要更新的內容,而不是您的數據是否已更改。 事實上, diff 算法本身就是一個臟檢查器,但它用於查看 DOM 是否臟。

我們的目標是僅在狀態改變時重新渲染虛擬樹。 因此,使用 observable 來檢查狀態是否已更改是防止不必要的重新渲染的有效方法,這會導致許多不必要的樹差異。 如果一切都沒有改變,我們就什么都不做。

虛擬 DOM 很好,因為它讓我們可以像重新渲染整個場景一樣編寫代碼。 在幕后,我們想要計算一個補丁操作,更新 DOM 以符合我們的預期。 因此,雖然虛擬 DOM diff/patch 算法可能不是最佳解決方案,但它為我們提供了一種非常好的方式來表達我們的應用程序。 我們只是准確地聲明我們想要的東西,React/virtual-dom 會弄清楚如何讓你的場景看起來像這樣。 我們不必手動操作 DOM 或對之前的 DOM 狀態感到困惑。 我們也不必重新渲染整個場景,這可能比修補它的效率低得多。

我最近在這里閱讀了一篇關於 React diff 算法的詳細文章: http : //calendar.perfplanet.com/2013/diff/ 據我了解,讓 React 快速的原因是:

  • 批量 DOM 讀/寫操作。
  • 僅子樹的有效更新。

與臟檢查相比,IMO 的主要區別是:

  1. 模型臟檢查:每當調用setState時,React 組件都會顯式設置為臟,因此這里不需要比較(數據)。 對於臟檢查,(模型的)比較總是在每個摘要循環中發生。

  2. DOM 更新:DOM 操作非常昂貴,因為修改 DOM 也會應用和計算 CSS 樣式、布局。 從不必要的 DOM 修改中節省的時間可能比差異化虛擬 DOM 所花費的時間更長。

第二點對於非平凡模型(例如具有大量字段或大列表的模型)更為重要。 復雜模型的一個字段更改將導致僅涉及該字段的 DOM 元素所需的操作,而不是整個視圖/模板。

我真的很喜歡 Virtual DOM(尤其是服務器端渲染)的潛在力量,但我想知道所有的優點和缺點。

-- 操作

React 不是唯一的 DOM 操作庫。 我鼓勵您通過閱讀來自 Auth0 的這篇文章來了解替代方案,其中包括詳細的解釋和基准測試。 正如您所問的,我將在此處強調它們的優缺點:

React.js 的虛擬 DOM

在此處輸入圖片說明

優點

  • 快速高效的“差異化”算法
  • 多個前端(JSX,超標)
  • 輕到足以在移動設備上運行
  • 大量的牽引力和思想共享
  • 可以在沒有 React 的情況下使用(即作為獨立引擎)

缺點

  • DOM 的完整內存副本(更高的內存使用)
  • 靜態和動態元素之間沒有區別

Ember.js 的微光

在此處輸入圖片說明

優點

  • 快速高效的差分算法
  • 靜態元素和動態元素的區別
  • 100% 兼容 Ember 的 API(無需對現有代碼進行重大更新即可獲得好處)
  • DOM 的輕量級內存表示

缺點

  • 僅用於 Ember
  • 只有一個前端可用

增量 DOM

在此處輸入圖片說明

優點

  • 減少內存使用
  • 簡單的API
  • 輕松與許多前端和框架集成(從一開始就作為模板引擎后端)

缺點

  • 不如其他庫快(這是有爭議的,請參閱下面的基准)
  • 減少思想共享和社區使用

這是 React 團隊成員 Sebastian Markbåge 的評論,它闡明了一些觀點:

React 對輸出進行差異處理(這是一種已知的可序列化格式,DOM 屬性)。 這意味着源數據可以是任何格式。 它可以是不可變的數據結構和閉包內部的狀態。

Angular 模型不保留引用透明度,因此本質上是可變的。 您改變現有模型以跟蹤更改。 如果您的數據源每次都是不可變數據或新數據結構(例如 JSON 響應)怎么辦?

臟檢查和 Object.observe 不適用於閉包范圍狀態。

這兩件事顯然非常限制功能模式。

此外,當您的模型復雜性增加時,進行臟跟蹤的成本會越來越高。 然而,如果你只在可視化樹上做 diff,比如 React,那么它不會增長那么多,因為你能夠在任何給定點在屏幕上顯示的數據量受到 UI 的限制。 上面皮特的鏈接涵蓋了更多的性能優勢。

https://news.ycombinator.com/item?id=6937668

您可以閱讀本文( Virtual DOM和DOM之間的區別 ),了解Real DOM和Virtual DOM。 希望它能幫到你!

在 React 中,您的每個組件都有一個 state。這個 state 就像您可能在 knockout 或其他 MVVM 樣式庫中找到的可觀察對象。 本質上,React 知道何時重新渲染場景,因為它能夠觀察到此數據何時發生變化。 臟檢查比可觀察對象慢,因為您必須定期輪詢數據並遞歸檢查數據結構中的所有值。 相比之下,在 state 上設置一個值將向偵聽器發出信號,表明某些 state 已經更改,因此 React 可以簡單地偵聽 state 上的更改事件並排隊重新渲染。虛擬 DOM 用於高效地重新渲染DOM。 這與臟檢查您的數據並沒有真正的關系。 您可以使用帶或不帶臟檢查的虛擬 DOM 重新渲染。 你是對的,計算兩個虛擬樹之間的差異有一些開銷,但虛擬 DOM 差異是關於了解 DOM 中需要更新的內容,而不是你的數據是否已更改。 事實上,diff 算法本身就是一個臟檢查器,但它是用來查看 DOM 是否臟的。

我們的目標是僅在 state 更改時重新渲染虛擬樹。 因此,使用可觀察對象檢查 state 是否已更改是防止不必要的重新渲染的有效方法,這會導致許多不必要的樹差異。 如果什么都沒有改變,我們什么都不做。

Virtual Dom 不是由 react 發明的。 它是 HTML dom 的一部分。 它是輕量級的,並且與瀏覽器特定的實現細節分離。

我們可以將虛擬 DOM 視為 React 的 HTML DOM 的本地和簡化副本。 它允許 React 在這個抽象世界中進行計算,並跳過“真正的”DOM 操作,這些操作通常很慢且特定於瀏覽器。 實際上,DOM 和 VIRTUAL DOM 之間沒有太大區別。

以下是使用 Virtual Dom 的原因( ReactJS 中的Virtual DOM ):

當你這樣做時:

 document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. 瀏覽器需要解析 HTML
  2. 它刪除了 elementId 的子元素
  3. 用新值更新 DOM 值
  4. 為父子重新計算css
  5. 更新布局,即每個元素在屏幕上的精確坐標
  6. 遍歷渲染樹並將其繪制在瀏覽器顯示上

重新計算 CSS 和更改的布局使用復雜的算法,它們會影響性能。

以及更新 DOM 屬性,即。 值。 它遵循一個算法。

現在,假設你直接更新 DOM 10 次,那么以上所有步驟都會一一運行,更新 DOM 算法需要時間來更新 DOM 值。

這就是 Real DOM 比 Virtual DOM 慢的原因。

暫無
暫無

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

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