vue中的虛擬dom知識點總結(jié)
一、簡介
虛擬dom是隨著時代發(fā)展而誕生的產(chǎn)物。 命令式操作dom:
- 簡單易用
- 程序中的狀態(tài)很難管理,代碼中的邏輯也很混亂。
現(xiàn)在三大主流框架都是聲明式操作DOM。通過描述狀態(tài)和DOM之間的映射關(guān)系,就可以將狀態(tài)渲染成視圖。狀態(tài)可以是JS 中的任意類型。將狀態(tài)作為輸入,并生成DOM輸出到頁面上顯示出來的過程叫渲染。 通常程序在運行時,狀態(tài)會不斷發(fā)生變化。狀態(tài)發(fā)生變化時,就需要重新渲染。 如何確定狀態(tài)中發(fā)生了什么變化以及需要在哪里更新DOM? 最簡單粗暴的解決方式:把所有DOM全刪了,使用狀態(tài)重新生成一份DOM,輸出到頁面上顯示出來。但是訪問dom是非常昂貴的,這樣會造成相當多的性能浪費。
虛擬DOM的解決方式:通過狀態(tài)生成虛擬節(jié)點樹,然后使用虛擬節(jié)點樹進行渲染。在渲染之前,會對比新舊虛擬DOM,只渲染不同的部分。 虛擬DOM是將狀態(tài)映射為視圖的眾多解決方案中的一種。
二、為什么VUE引入了虛擬DOM?
vue在一定程度上知道具體哪個狀態(tài)發(fā)生了變化和哪些節(jié)點使用了這個狀態(tài),這樣就可以通過更細粒度的綁定來更新視圖。代價是粒度太細會有很多watcher同時觀察某些狀態(tài),會有一些內(nèi)存開銷以及一些依賴追蹤的開銷。vue2.0采取了一個中等粒度的解決方案,狀態(tài)偵測只細化到某個組件,組件內(nèi)部通過虛擬DOM渲染視圖,這可以大大縮減依賴數(shù)量和watcher數(shù)量。 vue通過模板描述狀態(tài)和視圖之間的映射關(guān)系,它會先將模板編譯成渲染函數(shù),然后執(zhí)行渲染函數(shù)生成虛擬節(jié)點,使用虛擬節(jié)點更新視圖。
虛擬DOM在vue中的作用:
提供虛擬節(jié)點和對比新舊vnode,并根據(jù)對比結(jié)果進行DOM操作來更新視圖。
三、vnode
VNode類可以實例化不同類型的vnode實例,而不同類型的vnode實例各自表示不同類型的DOM元素。vnode可以理解為節(jié)點描述對象,描述了應(yīng)該怎么創(chuàng)建真實DOM。
1.vnode的類型
- 注釋節(jié)點:只有兩個有效屬性:isComment屬性和text屬性
- 文本節(jié)點:只有text屬性
- 元素節(jié)點:tag,data(節(jié)點的數(shù)據(jù):如attrs、class、style等),children,context(當前組件的vue實例)
- 組件節(jié)點:獨有屬性為componentOptions(組件節(jié)點的選項參數(shù)),componentInstance(組件實例)
- 函數(shù)式組件:類似于組件節(jié)點,獨有屬性為functionalContext和functionalOptions
- 克隆節(jié)點:將現(xiàn)有節(jié)點的屬性復(fù)制到新節(jié)點中,與被克隆節(jié)點的唯一區(qū)別是isCloned屬性,克隆節(jié)點的isCloned為true。作用是優(yōu)化靜態(tài)節(jié)點和插槽節(jié)點。
四、虛擬dom的核心——patch
可以將vnode渲染成真實的DOM,實際作用是計算出真正需要更新的節(jié)點,在現(xiàn)有DOM上進行修改來實現(xiàn)更新視圖的目的,最大限度減少DOM操作,顯著提升性能。本質(zhì)是用js的運算成本替換DOM操作的執(zhí)行成本,js的運算速度比DOM快得多,所以很劃算。
1.patch的過程
就是以新的vnode為準增刪改節(jié)點。
新增節(jié)點
- oldVnode不存在而vnode中存在。通常發(fā)生在首次渲染中。
- vnode和oldVnode完全不是同一個節(jié)點,vnode是新節(jié)點,而oldVnode是被廢棄的節(jié)點。
刪除節(jié)點
- 節(jié)點只在oldVnode中存在。
替換過程是將新創(chuàng)建的DOM節(jié)點插入到舊節(jié)點的旁邊,然后再將舊節(jié)點刪除。
更新節(jié)點
增刪節(jié)點的共同點是兩個虛擬節(jié)點完全不同。新舊節(jié)點是同一個文本節(jié)點,需要進行更細致的比對。
靜態(tài)節(jié)點
靜態(tài)節(jié)點:一旦渲染到頁面上就不會變化。 如果新舊兩個虛擬節(jié)點時靜態(tài)節(jié)點就直接跳過更新節(jié)點。
新虛擬節(jié)點有文本屬性
新虛擬節(jié)點有文本屬性而且和舊節(jié)點文本屬性不一樣,就直接調(diào)用setTextContent方法(在瀏覽器環(huán)境下是node.textContent方法)來將視圖中DOM節(jié)點的內(nèi)容改為虛擬節(jié)點的text屬性所保存的文本。
新虛擬節(jié)點無文本屬性
新虛擬節(jié)點有children:
- 舊虛擬節(jié)點也有children屬性,對新舊兩個虛擬節(jié)點的children進行更詳細的對比并更新(增刪改移)。
- 舊虛擬節(jié)點沒有children屬性,說明舊虛擬節(jié)點要么是一個空標簽,要么是有文本的文本節(jié)點。如果是文本節(jié)點,先把文本清空讓它變成空標簽,然后將新虛擬節(jié)點(vnode)中的children挨個創(chuàng)建成真實的DOM元素節(jié)點并將其插入到視圖中的DOM節(jié)點下面。
新虛擬節(jié)點無children:
沒有text也沒有children,說明是空節(jié)點。把舊虛擬節(jié)點刪成空標簽。
五、更新子節(jié)點的優(yōu)化策略
雙端對比。 只需要嘗試使用相同位置的兩個節(jié)點來比對是否是同一個節(jié)點:如果恰巧是同一個節(jié)點,直接就可以進入更新節(jié)點的操作;如果嘗試失敗了,再用循環(huán)的方式來查找節(jié)點。這樣做可以很大程度地避免循環(huán)oldChildren來查找節(jié)點,從而使執(zhí)行速度得到很大的提升。
- oldChildren先循環(huán)完畢,如果newChildren中還有剩余的節(jié)點,說明這些節(jié)點都是需要新增的節(jié)點,直接把這些節(jié)點插入到DOM中就行了。
- newChildren先循環(huán)完畢,、如果oldChildren還有剩余的節(jié)點,、說明oldChildren中剩余的節(jié)點都是被廢棄的節(jié)點,是應(yīng)該被刪除的節(jié)點。不需要循環(huán)對比就可以知道需要將這些節(jié)點從DOM中移除。
到此這篇關(guān)于vue中的虛擬dom知識點總結(jié)的文章就介紹到這了,更多相關(guān)vue中的虛擬dom內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項目中實現(xiàn)el-dialog組件可拖拽效果
本文主要介紹了vue項目中實現(xiàn)el-dialog組件可拖拽效果,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01關(guān)于在vue 中使用百度ueEditor編輯器的方法實例代碼
這篇文章主要介紹了在vue 中使用百度ueEditor編輯器的方法實例代碼 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09vue3.x源碼剖析之數(shù)據(jù)響應(yīng)式的深入講解
這篇文章主要給大家介紹了關(guān)于vue3.x源碼剖析之數(shù)據(jù)響應(yīng)式的相關(guān)資料,在講解過程中,我們會對比Vue2.x的API特性,使用有哪些區(qū)別,需要的朋友可以參考下2022-01-01