首頁 >微信小程式 >小程式開發 >怎麼使用React虛擬DOM

怎麼使用React虛擬DOM

php中世界最好的语言
php中世界最好的语言原創
2018-05-31 14:22:111989瀏覽

這次帶給大家怎樣使用React虛擬DOM,使用React虛擬DOM的注意事項有哪些,下面就是實戰案例,一起來看一下。

在Web開發中,需要將資料的變化即時反映到UI上,這時就需要對DOM進行操作,但是複雜或頻繁的DOM操作通常是效能瓶頸產生的原因,為此,React引入了虛擬DOM(Virtual DOM)的機制。

一、什麼是虛擬DOM?

在React中,render執行的結果得到的並不是真正的DOM節點,結果只是輕量級的JavaScript物件,我們稱之為virtual DOM。

虛擬DOM是React的一大亮點,具有batching(批次)和高效的Diff演算法。這讓我們可以無需擔心效能問題而」毫無顧忌」的隨時「刷新」整個頁面,由虛擬 DOM來確保只對介面上真正變化的部分進行實際的DOM操作。在實際開發中基本上不需要關心虛擬DOM是如何運作的,但是理解其運行機制不僅有助於更好的理解React組件的生命週期,而且對於進一步優化React程式也會有很大幫助。

二、虛擬DOM VS 直接操作原生DOM?

如果沒有 Virtual DOM,簡單來說就是直接重置 innerHTML。這樣操作,在一個大型列表所有資料都變了的情況下,還算是合理,但是,當只有一行資料發生變化時,它也需要重置整個 innerHTML,這時候顯然就造成了大量浪費。

比較innerHTML 和Virtual DOM 的重繪過程如下:

innerHTML: render html string 重新建立所有DOM 元素

Virtual DOM: render Virtual DOM diff 必要的DOM 更新

和DOM 運算比起來,js 計算是非常便宜的。 Virtual DOM render diff 顯然比渲染 html 字串慢,但是,它依然是純 js 層面的計算,比起後面的 DOM 操作來說,依然便宜了太多。當然,曾有人做過驗證說React的性能不如直接操作真實DOM,程式碼如下:

function Raw() {
  var data = _buildData(),
    html = "";
  ...
  for(var i=0; i<data.length; i++) {
    var render = template;
    render = render.replace("{{className}}", "");
    render = render.replace("{{label}}", data[i].label);
    html += render;
  }
  ...
  container.innerHTML = html;
  ...
}

該測試用例中雖然建構了一個包含1000個Tag的String,並把它加到DOM樹中,但是只做了一次DOM操作。然而,在實際開發過程中,這1000個元素更新可能分佈在20個邏輯塊中,每個邏輯塊中包含50個元素,當頁面需要更新時,都會引起DOM樹的更新,上述程式碼就近似變成瞭如下格式:

function Raw() {
  var data = _buildData(), 
    html = ""; 
  ... 
  for(var i=0; i<data.length; i++) { 
    var render = template; 
    render = render.replace("{{className}}", ""); 
    render = render.replace("{{label}}", data[i].label); 
    html += render; 
    if(!(i % 50)) {
      container.innerHTML = html;
    }
  } 
  ... 
}

這樣來看,React的效能就遠勝於原生DOM操作了。

而且,DOM 完全不屬於Javascript (也不在Javascript 引擎中存在).。 Javascript 其實是一個很獨立的引擎,DOM其實是瀏覽器引出的一組讓Javascript操作HTML文件的API而已。在即時編譯的時代,呼叫DOM的開銷是很大的。而Virtual DOM的執行完全都在Javascript 引擎中,完全不會有這個開銷。

React.js 相對於直接操作原生DOM有很大的效能優勢, 很大程度上都要歸功於virtual DOM的batching 和diff。 batching把所有的DOM操作蒐集起來,一次提交給真實的DOM。 diff演算法時間複雜度也從標準的Diff演算法的O(n^3)降到了O(n)。這裡留到下次部落格單獨講。

三、虛擬DOM VS MVVM?

相比起React,其他MVVM 系框架例如Angular, Knockout 以及Vue、Avalon 採用的都是資料綁定:透過Directive/Binding 對象,觀察資料變化並保留對實際DOM 元素的引用,當有資料變化時進行對應的操作。 MVVM 的變化檢查是資料層面的,而 React 的檢查是 DOM 結構層面的。 MVVM 的效能也根據變動偵測的實作原理有所不同:Angular 的髒檢查使得任何變動都有固定的O(watcher count) 的代價;Knockout/Vue/Avalon 都採用了依賴收集,在js 和DOM 層面都是O(change):

  1. 髒檢查:scope digest 必要DOM 更新

  2. 依賴收集:重新收集依賴必要DOM 更新

可以看到,Angular 最不效率的地方在於任何小變動都有的和 watcher 數量相關的效能代價。但是!當所有數據都改變了的時候,Angular 其實並不吃虧。依賴收集在初始化和資料變化的時候都需要重新收集依賴,這個代價在小量更新的時候幾乎可以忽略,但在資料量龐大的時候也會產生一定的消耗。

MVVM 渲染清單的時候,由於每一行都有自己的資料作用域,所以通常都是每一行都有一個對應的ViewModel 實例,或者是一個稍微輕量一些的利用原型繼承的"scope " 對象,但也有一定的代價。所以,MVVM 清單渲染的初始化幾乎一定比 React 慢,因為建立 ViewModel / scope 實例比起 Virtual DOM 來說要昂貴很多。這裡所有 MVVM 實作的一個共同問題就是在清單渲染的資料來源變動時,尤其是當資料是全新的物件時,如何有效地重複使用已建立的 ViewModel 實例和 DOM 元素。假如沒有任何復用方面的最佳化,由於資料是 「全新」 的,MVVM 實際上需要銷毀之前的所有實例,重新建立所有實例,最後再進行一次渲染!這就是為什麼題目裡連結的 angular/knockout 實作都相對比較慢。相較之下,React 的變動檢查由於是 DOM 結構層面的,即使是全新的數據,只要最後渲染結果沒變,那麼就不需要做無用功。

Angular 和 Vue 都提供了清單重繪的最佳化機制,也就是 「提示」 框架如何有效地重複使用實例和 DOM 元素。例如資料庫裡的同一個對象,在兩次前端 API 呼叫裡面會成為不同的對象,但是它們還是有一樣的 uid。這時候你就可以提示 track by uid 來讓 Angular 知道,這兩個物件其實是同一份資料。那麼原來這份資料對應的實例和 DOM 元素都可以重複使用,只需要更新變動了的部分。或者,你也可以直接 track by $index 來進行 “原地復用”:直接根據在數組裡的位置進行複用。在題目所舉的例子裡,如果 angular 實作加上 track by $index 的話,後續重繪是不會比 React 慢多少的。甚至在dbmonster 測試中,Angular 和Vue 用了track by $index 以後都比React 快: dbmon (注意Angular 預設版本無優化,優化過的在下面)

#在比較效能的時候,要分清楚初始渲染、小量資料更新、大量資料更新這些不同的場合。 Virtual DOM、髒檢查 MVVM、資料收集 MVVM 在不同場合各有不同的表現和不同的最佳化需求。 Virtual DOM 為了提升小量資料更新時的效能,也需要針對性的最佳化,例如 shouldComponentUpdate 或是 immutable data。

  1. 初始渲染:Virtual DOM > 髒檢查>= 依賴收集

  2. 小量資料更新:依賴收集>> Virtual DOM 優化> 髒檢查(無法優化) > Virtual DOM 無優化

  3. 大量資料更新:髒檢查優化>= 依賴收集優化> Virtual DOM(無法/無需優化)>> MVVM 無最佳化

  4. (該段落借鑒了知乎的相關答案)

  5. ## 四、對React虛擬DOM的誤解?

    React 從來沒有說過 「React 比原生操作 DOM 快」。 React給我們的保證是,在不需要手動優化的情況下,它依然可以提供我們過得去的效能。

    React掩蓋了底層的 DOM 操作,可以用更宣告式的方式來描述我們目的,讓程式碼更容易維護。以下也藉鑒了知乎上的回答:沒有任何框架可以比純手動的優化 DOM 操作更快,因為框架的 DOM 操作層需要應對任何上層 API 可能產生的操作,它的實作必須是普適的。針對任何一個 benchmark,我都可以寫出比任何框架更快的手動優化,但是那有什麼意義呢?在建立一個實際應用的時候,你難道為每個地方都去做手動優化嗎?出於可維護性的考慮,這顯然不可能。

    相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

    推薦閱讀:

    微信小程式內實作上傳圖片附後端程式碼

    微信小程式上傳圖片實戰案例解析

    以上是怎麼使用React虛擬DOM的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn