談談虛擬dom和diff演算法

seven同學發表於2020-04-06

我喜歡帶著問題去學習一個東西。所以,在開始看這篇文章開始之前,我先問大家一個問題。

  • vuejs解決了什麼問題?

這裡所說的解決的問題是和以前的開發模式比,在沒有此類mvvm框架之前,我們主要是通過jquery來開發。通過jquery來開發個人感覺有兩點不夠友好

  • 開發者需要過多的關注於如何操作dom
  • 在涉及到頻繁的操作dom時,效能不夠好。我們比較難做到如何精準定位到真正需要更新的dom和何時去更新

針對第二點我們來做個說明

假設我們有如下情景,在一個頁面中,一個變數的改變會引起頁面中其餘多個變數的改變並要在頁面中體現出來。在以前的開發模式下,我們需要手動的改變那多個變數。並且在有些場景下我們很難做到精準定位。

vuejs是漸進式框架

所謂漸進式框架,我們可以從如下兩個方面來理解

  • 你可以根據你自己專案的需求有選擇性的去採用自己所需的技術棧。例如你的專案不涉及到路由或者複雜的狀態管理,那麼你完全可以不用vue-router 和 vuex
  • 假設你有個專案是通過html寫的,但是現在某塊內容需要設計到比較複雜的dom和資料之間的互動,那麼你可以只對這一塊內容採用vuejs

vuejs 整體執行過程

談談虛擬dom和diff演算法

這種圖從整體上描述了vuejs的執行機制,我們今天主要對其中的patch過程進行分析

在理解patch過程之前我們先來了解下如下幾個概念

  • 什麼是DOM
  • 什麼是虛擬DOM
  • 加入虛擬DOM的作用是什麼
  • 虛擬dom如何和真實的dom關聯起來
  • 加入虛擬dom的好處

什麼是DOM

文件物件模型(DOM)是HTML 和 XML 文件的程式設計介面。它提供了對文件的結構化的表述,並定義了一種方式可以使從程式中對該結構進行訪問,從而改變文件的結構,樣式和內容。DOM將文件解析為一個由節點和物件(包含屬性和方法的物件)組成的結構集合。簡言之,它會將web頁面和指令碼或程式語言連線起來

談談虛擬dom和diff演算法

什麼是虛擬DOM

用js物件來描述dom節點比較重要的資訊(tag類別,子節點,父節點等等)

github.com/vuejs/vue/b…

對比下通過通過直接操作dom 和 通過虛擬dom 開發的區別

談談虛擬dom和diff演算法

我們可以看到當採用了vuejs以後,我們不需要直接關心資料和dom是如何關聯的

虛擬dom如何和真實的dom關聯起來

虛擬節點會有elm屬性儲存該虛擬節點所對應的真實節點(mounted)

虛擬dom有什麼好處呢?

  • 開發者不需要關心如何操作dom
  • 讓跨平臺成為了可能
  • 可以增加patch過程,提高效能
  • 讓我們的開發模式變成了只需要關心資料

如果讓你設計diff演算法,你該如何設計?

通過上述分析,我們知道vuejs在需要更新頁面的時候會先對比虛擬節點,然後再更新真實dom,所以我們可以考慮如下幾個點

  • 能複用的儘量複用舊元素
  • 儘可能的一次性刪除不需要的舊節點
  • 儘可能的一次性增加新的節點

我們通過幾個例子來分析

談談虛擬dom和diff演算法

changeName 新老節點對比

談談虛擬dom和diff演算法

從虛擬節點樹上可以看出,我們只是從 bob 改變成了 alice 其他的都可以複用

changeIsNeedShowInterests 新老節點對比

談談虛擬dom和diff演算法

我們可以看到這次我們只需要刪除ul就行,別的都能複用

changeInterests 新老節點對比

談談虛擬dom和diff演算法

這次只需要將第一個li元素的文字改和新增加一個li元素就行

vuejs採用了雙索引和層級遍歷

談談虛擬dom和diff演算法

key的作用?

1:方便快速判斷新老節點是否相等
2:方便快速確定新節點在老節點裡是否存在

相關文章