關(guān)于Vue虛擬dom問題
一、什么是虛擬dom?
虛擬dom本質(zhì)上就是一個(gè)普通的JS對(duì)象,用于描述視圖的界面結(jié)構(gòu)
在vue中,每個(gè)組件都有一個(gè)render函數(shù),
沒有render找template,沒有template找el,有el就會(huì)把el.outHTML作為template,然后把這串字符串編譯成render函數(shù)。
有template就不往下找了。有render同理。
每個(gè)render 函數(shù)都會(huì)返回一個(gè)虛擬dom樹,這也就意味著每個(gè)組件都對(duì)應(yīng)一棵虛擬DOM樹。
也就是說render目的就是創(chuàng)建虛擬dom,這個(gè)組件到底要顯示啥。
console.log(‘render'); ↓
題外:console.dir()可以顯示一個(gè)對(duì)象所有的屬性和方法。
如果沒有return,這時(shí)候在頁面中是不存在真實(shí)dom的。
加上return↓
h函數(shù)名字是自定義的,h函數(shù)結(jié)構(gòu),h(標(biāo)簽,{自身屬性},[子元素])
子元素繼續(xù)用h函數(shù)建,因?yàn)橛袆e的屬性
我們?cè)赱 ]里面再創(chuàng)建一個(gè)子元素
h函數(shù)做了判斷,如果不是對(duì)象,就是文本節(jié)點(diǎn)了,↑認(rèn)為是省略掉了中間的配置
在頁面內(nèi)渲染出來。
console.log(vnode);
h1子元素↓
通過.elm對(duì)應(yīng)真實(shí)結(jié)點(diǎn)
h(‘h1','{{title}}')這種是肯定不行的,必須h(‘h1',this.title)
二、為什么需要虛擬dom
在vue 中,渲染視圖會(huì)調(diào)用render 函數(shù),這種渲染不僅發(fā)生在組件創(chuàng)建時(shí),同時(shí)發(fā)生在視圖依賴的數(shù)據(jù)更新時(shí)。如果在渲染時(shí),直接使用真實(shí) DOM ,由于真實(shí)DOM的創(chuàng)建、更新、插入等操作會(huì)帶來大量的性能損耗,從而就會(huì)極大的降低渲染效率。
因此, vue 在渲染時(shí),使用虛擬dom來替代真實(shí)dom,主要為解決渲染效率的問題。
生成真實(shí)dom在第一次加載的時(shí)候沒有任何問題,因?yàn)闊o法避免,必要要生成真實(shí)dom。
render函數(shù)不止生成一次,它是每一次數(shù)據(jù)變化都要生成。
但是如果在render里用createElement每次都會(huì)生成全新的dom元素,開銷太大了
三、虛擬dom是如何轉(zhuǎn)換為真實(shí)dom的
在一個(gè)組件實(shí)例首次被渲染時(shí),它先生成虛擬dom樹,深度優(yōu)先遍歷結(jié)點(diǎn),setAttribute,然后根據(jù)虛擬dom樹創(chuàng)建真實(shí)dom,并把真實(shí)dom掛載到頁面中合適的位置,直接替換掉div#app,此時(shí),每個(gè)虛擬dom便會(huì)對(duì)應(yīng)一個(gè)真實(shí)的dom。
是不等于的,因?yàn)橹苯犹鎿Q掉了div#app
如果一個(gè)組件受響應(yīng)式數(shù)據(jù)變化的影響,需要重新渲染時(shí),它仍然會(huì)重新調(diào)用render函數(shù),創(chuàng)建出一個(gè)新的虛擬dom樹,用新樹和舊樹對(duì)比,通過對(duì)比,vue會(huì)找到最小更新量,然后更新必要的真實(shí)dom節(jié)點(diǎn)
這樣一來,就保證了對(duì)真實(shí)dom達(dá)到最小的改動(dòng)。
通過diff算法查看那兩個(gè)虛擬dom是不一樣的,然后去改動(dòng)對(duì)應(yīng)結(jié)點(diǎn)的真實(shí)dom完成效果,保證改動(dòng)最少,提高效率
四、模板和虛擬dom的關(guān)系
腳手架搭的虛擬dom
vue框架中有一個(gè)compile模塊,它主要負(fù)責(zé)將模板轉(zhuǎn)換為render函數(shù),而render函數(shù)調(diào)用后將得到虛擬dom。
編譯的過程分兩步,(babel和webpack都是這么創(chuàng)建的):
將模板字符串轉(zhuǎn)換成為AST(抽象語法樹,用樹形結(jié)構(gòu)描述我們的東西)將AST轉(zhuǎn)換為render函數(shù)
AST↓,提一嘴AST用棧搭建的
如果使用傳統(tǒng)的引入方式(src),則編譯時(shí)間發(fā)生在組件第一次加載時(shí),這稱之為運(yùn)行時(shí)編譯。再提一嘴,第1步非常耗時(shí)。
如果是在vue-cli的默認(rèn)配置下,編譯發(fā)生在打包時(shí),這稱之為模板預(yù)編譯。
編譯是一個(gè)極其耗費(fèi)性能的操作,預(yù)編譯可以有效的提高運(yùn)行時(shí)的性能,而且,由于運(yùn)行的時(shí)候已不需要編譯,vue-cli在打包時(shí)會(huì)排除掉vue中的compile模塊,以減少打包體積
如果上面不寫模板template
會(huì)報(bào)錯(cuò),但是你可以在vue.config.js配置
module.export={runtimeCompiler:true}
不建議,會(huì)加入編譯內(nèi)容,使內(nèi)容變多。(再提一嘴esbuild和vite加速打包,?沒用過)
模板的存在,僅僅是為了讓開發(fā)人員更加方便的書寫界面代碼
vue最終運(yùn)行的時(shí)候,最終需要的是render函數(shù),而不是模板,因此,模板中的各種語法,在虛擬dom中都是不存在的,它們都會(huì)變成虛擬dom的配置
等同于
案例:自動(dòng)生成目錄
現(xiàn)在需要制作一個(gè)組件,該組件可以根據(jù)其插槽中的內(nèi)容,自動(dòng)生成一個(gè)目錄。
到此這篇關(guān)于關(guān)于Vue虛擬dom問題的文章就介紹到這了,更多相關(guān)Vue虛擬dom內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家
相關(guān)文章
關(guān)于vue-router的beforeEach無限循環(huán)的問題解決
本篇文章主要介紹了關(guān)于vue-router的beforeEach無限循環(huán)的問題解決,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09vue form表單post請(qǐng)求結(jié)合Servlet實(shí)現(xiàn)文件上傳功能
這篇文章主要介紹了vue form表單post請(qǐng)求結(jié)合Servlet實(shí)現(xiàn)文件上傳功能,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01vue實(shí)現(xiàn)一個(gè)移動(dòng)端屏蔽滑動(dòng)的遮罩層實(shí)例
本篇文章主要介紹了vue實(shí)現(xiàn)一個(gè)移動(dòng)端屏蔽滑動(dòng)的遮罩層實(shí)例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-06-06Vue3管理后臺(tái)項(xiàng)目使用高德地圖選點(diǎn)的實(shí)現(xiàn)
本文主要介紹了Vue3管理后臺(tái)項(xiàng)目使用高德地圖選點(diǎn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07vue + typescript + video.js實(shí)現(xiàn) 流媒體播放 視頻監(jiān)控功能
視頻才用流媒體,有后臺(tái)實(shí)時(shí)返回?cái)?shù)據(jù), 要支持flash播放, 所以需安裝對(duì)應(yīng)的flash插件。這篇文章主要介紹了vue + typescript + video.js 流媒體播放 視頻監(jiān)控,需要的朋友可以參考下2019-07-07