【Vue】diff 算法

  1. diff的時機

    當組件創建時,以及依賴的屬性或數據變化時,會運行一個函數,該函數會做兩件事:

    • 運行_render生成一棵新的虛擬dom樹(vnode tree),返回根節點
    • 運行_update,傳入虛擬dom樹的根節點,對新舊兩棵樹進行對比,最終完成對真實dom的更新

    核心代碼如下:

    function Vue() {// ...let updateComponent = () => {this._update(this._render())}new Watcher(updateComponent)// ...
    }
    

    diff就發生在_update函數的運行過程中。

  2. _update函數在干什么

    _update函數接收到一個vnode參數,這就是新生成的虛擬dom樹。

    同時,update函數通過當前組件的_vnode屬性,拿到舊的虛擬dom樹。

    _update函數首先會給組件的_vnode屬性重新賦值,讓它指向新樹。

    function update(vnode) {// vnode 新節點// this._vnode 舊節點let oldVNode = this._vnodethis._vnode = vnode// 對比新舊節點 更新真實 dom}
    

    然后會判斷舊樹存不存在:

    • 不存在:說明這是第一次加載組件,于是通過內部的patch函數,直接遍歷新樹,為每個節點生成真實DOM,掛載到每個節點的elm屬性上
    if (!oldVNode) {this.__patch__(this.$el, vnode)
    }
    
    • 存在:說明之前已經渲染過該組件,于是通過內部的patch函數,對新舊兩棵樹進行對比,以達到下面兩個目標:
      • 完成對所有真實dom的最小化處理
      • 讓新樹的節點對應合適的真實dom
  3. patch 函數的對比流程

    術語解釋:

    1. 「相同」:是指兩個虛擬節點的標簽類型、key值均相同,但input元素還要看type屬性
    2. 「新建元素」:是指根據一個虛擬節點提供的信息,創建一個真實dom元素,同時掛載到虛擬節點的elm
      屬性上
    3. 「銷毀元素」:是指:vnode.elm.remove(), 移除真實 dom 元素
    4. 「更新」:是指對兩個虛擬節點進行對比更新,它僅發生在兩個虛擬節點「相同」的情況下
    5. 「對比子節點」:是指對兩個虛擬節點的子節點進行對比,深度優先遍歷

    詳細流程:

    1. 根節點比較

    patch函數首先對根節點進行比較。

    如果兩個節點:

    • 「相同」,進入「更新」流程
      1. 將|舊節點的真實dom賦值到新節點:newVnode.elm=oldVnode.elm
      2. 對比新節點和舊節點的屬性,有變化的更新到真實dom中
      3. 當前兩個節點處理完畢,開始「對比子節點」
    • 不「相同」
      1. 新節點遞歸「新建元素」
      2. 舊節點「銷毀元素」
    1. 「對比子節點」
    • 盡量少的進行操作
    • 不行的話,盡量僅改動元素屬性
    • 還不行的話,盡量移動元素,而不是刪除和創建元素
    • 還不行的話,刪除和創建元素

總結

當組件創建和更新時,vue均會執行內部的update函數,該函數使用render函數生成虛擬dom樹,將新舊兩樹進行對比,找到差異點,最終更新到真實dom。

對比差異的過程叫diff,Vue在內部通過一個叫patch的函數完成該過程。

在對比時,Vue采用深度優先、同層比較的方式進行比對。

在判斷兩個節點是否相同時,vue是通過虛擬節點的key和tag來進行判斷的。

具體來說,首先對根節點進行對比,如果相同則將舊節點關聯的真實 dom 的引用掛到新節點上,然后根據需
要更新屬性到真實 dom,然后再對比其子節點數組;如果不相同,則按照新節點的信息遞歸創建所有真實
dom,同時掛到對應虛擬節點上,然后移除掉舊的dom。

在對比其子節點數組時,Vue 對每個子節點數組使用了兩個指針,分別指向頭尾,然后不斷向中間靠攏來進行
對比,這樣做的目的是盡量復用真實dom,盡量少的銷毀和創建真實dom。如果發現相同,則進入和根節點一樣的對比流程,如果發現不同,則移動真實dom到合適的位置。

這樣一直遞歸的遍歷下去,直到整棵樹完成對比。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15222.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15222.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15222.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

typedef定義結構體包含函數指針的巨坑

起因 嘗試在c中模仿c的類,把成員函數放置到結構體中。顯然只能放置一個結構體指針。 于是準備這么做。 錯誤示范 typedef struct {int id;void(*show)(Person p); }Person;void showPerson(Person p){ //.... }void init(Person * p){p->show showPerson; …

犀牛8 for Mac/Win:重塑三維建模的新標桿

在數字創意的浪潮中,犀牛8(Rhinoceros 8)作為一款卓越的三維建模軟件,以其強大的功能和出色的性能,在Mac和Windows平臺上都贏得了廣大設計師和工程師的青睞。 犀牛8不僅繼承了前代產品的優秀基因,更在細節…

基于python+Django+opencv的疲勞檢測系統設計與實現

博主介紹: 大家好,本人精通Java、Python、C#、C、C編程語言,同時也熟練掌握微信小程序、Php和Android等技術,能夠為大家提供全方位的技術支持和交流。 我有豐富的成品Java、Python、C#畢設項目經驗,能夠為學生提供各類…

Nginx的集群負載均衡(nginx構建tomcat集群案例)

一 .Nginx的集群負載均衡 1.nginx 集群負載均衡示意圖 2.四層負載均衡和7層負載均衡 LVS 四層負載均衡(常用); Haproxy四層負載均衡;Nginx 四層負載均衡; Haproxy七層負載均衡;Nginx 七層負載均衡(常用); 3.nginx構建tomcat集群 步驟1:安裝tomcat 步驟2:nginx配置tom…

夸夸生肖屬鼠的女性朋友

屬鼠人一生的命運受到許多因素的影響,包括性格、家庭、教育、環境等。屬鼠人性格外向、求知欲強、善解人意、善于結交各種各樣的朋友,有豐富的人脈,容易得到他人的幫助和支持。 屬鼠的人聰明、機智,他們善于觀察,富有…

MySQL(七) 表的內連和外連

表的連接分為內連和外連 9.1 內連接 內連接實際上就是利用where子句對兩種表形成的笛卡兒積進行篩選,我們前面學習的查詢都是內連接,也是在開發過程中使用的最多的連接查詢。 語法: select 字段 from 表1 inner join 表2 on 連接條件 and …

【代碼隨想錄】面試常考類型之動態規劃基礎題目

前言 更詳細的在大佬的代碼隨想錄 (programmercarl.com) 本系列僅是簡潔版筆記,為了之后方便觀看 做題步驟 含義公式初始化順序檢查 確定dp數組以及下標的含義遞推公式dp數組如何初始化遍歷順序打印dp數組(看哪里有問題) 斐波那契數 …

MFC:CFileFind類使用方法介紹

這是一個介紹MFC中CFileFind類的小程序。編寫這個程序使用的編輯軟件是VS2022&#xff0c;基于C空項目。在C空項目下要調用MFC類需要&#xff1a;首先&#xff0c;頭文件要包含<afx.h>&#xff0c;這個頭文件包含了絕大部分使用MFC所需頭文件&#xff1b;其次&#xff0c…

在線改圖片怎么做更簡單?快速修改圖片尺寸的方法

現在一般拍攝出的圖片尺寸都會比較大&#xff0c;想要上傳大網上的一些平臺展示時&#xff0c;經常會受到平臺的限制&#xff0c;無法將圖片正常上傳到平臺&#xff0c;那么如何將圖片尺寸快速調整呢&#xff1f;比較簡單的一種方式&#xff0c;可以通過在線改圖片的工具來實現…

一個開源的個人主頁模板,可以通過 Github Actions 來進行自動構建。

無名の主頁 簡單的小主頁&#xff0c;原來的看夠了&#xff0c;重新弄了一個 主頁的 Logo 字體已經過壓縮&#xff0c;若用本站 Logo 以外的字母會變回默認字體&#xff0c;這里是 完整字體&#xff0c;若無法下載&#xff0c;可將字體目錄下的 Pacifico-Regular-all.ttf 進行替…

Linux程序開發(十一):進程與進程間通信設計之趣味貓咪抓老鼠游戲

Tips&#xff1a;"分享是快樂的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不僅有知識的海洋&#x1f30a;&#xff0c;還有滿滿的正能量加持&#x1f4aa;&#xff0c;快來和我一起分享這份快樂吧&#x1f60a;&#xff01; 喜歡我的博客的話&#xff0c;記得…

他用AI,抄襲了我的AI作品

《大話西游》里面有一句經典臺詞&#xff1a;每個人都有一個媽&#xff0c;但是“你媽就一定是你媽嗎&#xff1f;” 用AI創作的藝術作品&#xff0c;也走進類似的困境&#xff1a;如何證明你用AI生成的作品&#xff0c;就是你的作品&#xff1f; 近日&#xff0c;騰訊科技獨…

Google手機連接wifi后提示“無法連接互聯網“解決方法

1.原因分析 谷歌手機聯網前會先訪問谷歌的服務器:http://clients3.google.com/generate_204來探測網絡是否連通&#xff0c;由于國內網絡防火墻的原因訪問不了&#xff0c;所以就提示"無網絡連接"。 2.解決方法 可以通過adb命令修改驗證網絡是否連通的服務器地址&…

SpringCloudAlibaba:6.3SpringBoot接入RocketMQ

依賴 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 htt…

【C++提高編程-04】----C++之Vector容器實戰

&#x1f3a9; 歡迎來到技術探索的奇幻世界&#x1f468;?&#x1f4bb; &#x1f4dc; 個人主頁&#xff1a;一倫明悅-CSDN博客 ?&#x1f3fb; 作者簡介&#xff1a; C軟件開發、Python機器學習愛好者 &#x1f5e3;? 互動與支持&#xff1a;&#x1f4ac;評論 &…

STM32+CubeMX移植SPI協議驅動W25Q16FLash存儲器

STM32CubeMX移植SPI協議驅動W25Q16FLash存儲器 SPI簡介拓撲結構時鐘相位&#xff08;CPHA&#xff09;和時鐘極性&#xff08; CPOL&#xff09; W25Q16簡介什么是Flash&#xff0c;有什么特點&#xff1f;W25Q16內部塊、扇區、頁的劃分引腳定義通訊方式控制指令原理圖 CubeMX配…

iBarcoder for Mac v3.15.1中文激活版:讓條形碼生成變得如此簡單

在現代社會&#xff0c;條形碼無處不在&#xff0c;從超市商品到物流包裹&#xff0c;都離不開它的身影。iBarcoder for Mac作為一款簡單易用的條形碼生成軟件&#xff0c;讓條形碼的生成變得如此簡單。 iBarcoder for Mac v3.15.1中文激活版下載 無論你是需要為商品添加條形碼…

Scrapy框架簡單介紹及Scrapy項目編寫詳細步驟

引言 Scrapy是一個用Python編寫的開源、功能強大的網絡爬蟲框架&#xff0c;專為網頁抓取和數據提取設計。它允許開發者高效地從網站上抓取所需的數據&#xff0c;并通過一系列可擴展和可配置的組件來處理這些數據。Scrapy框架的核心組成部分包括&#xff1a; Scrapy Engine&…

aws glue配置讀取本地kafka數據源

創建連接時填寫本地私有ip地址&#xff0c;選擇網絡配置 配置任務選擇kafka作為數據源 但是執行任務時日志顯示連接失敗 文檔提到只能用加密通信 如果您希望與 Kafka 數據源建立安全連接&#xff0c;請選擇 Require SSL connection (需要 SSL 連接)&#xff0c;并在 Kafka priv…

python批發模塊的調試之旅:從新手到專家的蛻變

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、調試技巧的重要性 二、批發模塊調試的實戰演練 1. 設置斷點 2. 逐行執行代碼 3. 觀察…