一文帶你了解vue之虛擬dom

在面試的過程中,可能也會被問到對虛擬dom的理解,像這種面試題是比較寬泛的,面試官想知道你到底知道多少?既然是理解,那就只能是知無不言言無不盡,盡量組織下語言多說點,這樣才顯得專業(yè)素養(yǎng)比較高,接下來,我來談談自己的理解,切記不要去背,一定要理解之后,用自己的語言來描述出來。
我們可以從以下四個方面來回答:
?? 什么是虛擬dom
虛擬dom本質上就是一個普通的JS對象,用來描述視圖上應該有哪些界面結構,并不生成界面。我們可以在生命周期「mounted階段」打印一下this._vnode,如下:
描述了標簽為div、有哪些屬性、以及有哪些子元素等等,它通過普通的js對象這種形式來描述頁面上應該有哪些東西,但并不會生成界面。

在vue中,每個組件都有一個render函數,每一個render函數都會返回一個虛擬dom數,這也就意味著每個組件都對應一棵虛擬DOM樹。

?? 為什么需要虛擬dom
這個主要是由vue框架結構所決定的,在vue中,渲染視圖會調用render函數,這種渲染不僅發(fā)生在組件創(chuàng)建時,而且還會發(fā)生在依賴的數據更新的時候。如果在渲染時,直接使用真實DOM,由于真實DOM的創(chuàng)建、更新、插入等操作會帶來大量的性能消耗,從而會極大的降低渲染效率。
「示例」:對比創(chuàng)建js對象和創(chuàng)建真實dom對象進行用時對比
<script>
var times = 10000000;//次數為1000萬次
//js對象
console.time(`js object`);
for (var i = 0; i < times; i++) {
var obj = {};
}
console.timeEnd("js object");
//真實dom對象
console.time(`dom object`);
for (var i = 0; i < times; i++) {
var obj = document.createElement("div");
}
console.timeEnd("dom object");
</script>
「運行結果」:

從結果看,js對象用時150ms,而真實dom用時將近7s了,這個還不算插入到頁面中導致的重繪重排時間,非常恐怖!
因此,vue在渲染時,使用虛擬dom來代替真實dom,主要為解決渲染效率的問題。那光有虛擬dom也不能夠啊,那頁面咋顯示呢?總不能是無字天書吧!接下來就是第三個方面了
?? 虛擬dom是如何轉換為真實dom的
在一個組件實例第一次被渲染的時候,它會先生成虛擬dom樹,然后根據虛擬dom樹創(chuàng)建真實dom,最后會把真實的dom掛載到頁面中合適的位置,所以說,創(chuàng)建真實的dom這一步是少不了的,只能說盡量的少創(chuàng)建,如果說頁面只需要渲染一次,后面的數據變化都不重新渲染頁面,這時vue的效率跟直接操作dom效率相比其實是更加低的,因為它比直接操作dom還多一個步驟:創(chuàng)建虛擬dom。第一次vue渲染效率是不高的,但是后續(xù)就不一樣了。
如果一個組件受到響應式數據變化的影響,需要重新渲染時,它仍然會重新調用render函數,創(chuàng)建一個新的虛擬dom樹,這時會用新虛擬dom樹(newVnode)和舊虛擬dom樹(oldVnode)進行對比,通過比對,vue會找到最小更新量,然后更新必要的虛擬dom節(jié)點,最后,這些更新過的虛擬節(jié)點會去修改它們對應的真實dom。這樣一來就保證了對真實dom的操作達到了最小的改動。

比對過程其實是用到了一個算法,叫patch,它可以判斷出哪些節(jié)點發(fā)生了變化,從而只對發(fā)生變化的虛擬dom節(jié)點進行更新,關于patch我會專門出一篇文章談談自己的看法。
?? 模板和虛擬dom的關系
vue框架中有一個compile模塊,它主要負責將模板轉換為render函數,而render函數調用后得到虛擬dom。
編譯過程分為兩步:
將模板字符串轉換為AST(Abstract Syntax Tree,抽象語法樹) 將AST轉換為render函數
如果使用傳統(tǒng)的引入方式(使用script標簽引入vue.js),編譯時間發(fā)生在組件第一次加載時,被稱為
運行時編譯。如果是在vue-cli默認配置下,編譯發(fā)生在打時,被稱為
模板預編譯。
編譯是一個極其耗費性能的操作,預編譯可以有效的提高運行時的性能,而且,由于運行時已經不需要編譯,vue-cli在打包時會排除掉vue中的compile模塊,這樣可以減少打包體積。
模板的存在,僅僅只是為了我們更加方便的書寫界面代碼,vue最終運行的時候,最終需要的是render函數,而不是模板,這里要注意的是vue它是不認識模板的,模板是vue-cli預編譯所需要的,它最終會將模板編譯成render函數提供給vue正常運行。因此模板中的各種語法,在虛擬dom中都是不存在的,它們都會變成虛擬dom的配置。
?? 好了, 以上就是我的分享,大家對于虛擬dom還有其它理解的話可以在評論區(qū)討論鴨~
記得點贊 ?? 支持一下哦~ ??
