【Vuejs】1017- Vue3 效率提升主要表现在哪些方面?
vue3.0的各種表現(xiàn)還是非常棒的,相比vue2.0確實上了一個臺階,據(jù)說在客戶端渲染效率比vue2提升了1.3~2倍,SSR渲染效率比vue2提升了2 ~3倍。在面試的過程中可能也會被問到。
???? 靜態(tài)提升
vue中有個編譯器,在vue3的package.json文件中有個@vue/compiler-sfc,vue2中叫vue-template-compiler,這兩個就是編譯器,它會把我們的模板編譯為render函數(shù),在vue3中編譯器是很智能的,在編譯的過程中,它可以發(fā)現(xiàn)哪些節(jié)點是靜態(tài)節(jié)點,什么是靜態(tài)節(jié)點?
靜態(tài)節(jié)點就是一個元素節(jié)點,而且這個節(jié)點里面沒有任何動態(tài)的內(nèi)容,就是說沒有綁定任何動態(tài)的屬性,這叫靜態(tài)節(jié)點,比如:
<template><img?alt="Vue?logo"?src="./assets/logo.png"?/><HelloWorld?msg="Hello?Vue?3.0?+?Vite"?/> </template>上述代碼中的img就是靜態(tài)節(jié)點,它沒有綁定任何動態(tài)的內(nèi)容
然而vue3的編譯器會發(fā)現(xiàn)靜態(tài)節(jié)點,然后將它進行提升,但是在vue2中它是不在乎是靜態(tài)節(jié)點,還是動態(tài)節(jié)點,一頓操作猛如虎,下面對比下:
//vue2?的靜態(tài)節(jié)點 render(){//創(chuàng)建一個虛擬節(jié)點h1,沒有任何屬性,只有內(nèi)容為"法醫(yī)",編譯后?<h1>法醫(yī)</h1>createVNode("h1",null,"法醫(yī)");//....其他代碼 }//vue3?的靜態(tài)節(jié)點 const?hoisted?=?createVNode("h1",null,"法醫(yī)"); function?render(){//直接使用?hoisted就可以了 }在vue3中,它覺得這既然是一個靜態(tài)節(jié)點,那么肯定是不會變化的,不可能說這一次是h1元素內(nèi)容是法醫(yī),下次變成h2元素內(nèi)容是別的了,所以說vue3認為既然是靜態(tài)節(jié)點,那么就沒有必要在render函數(shù)中進行創(chuàng)建,因為一旦數(shù)據(jù)改變,render函數(shù)會反復(fù)運行,然后又會重新創(chuàng)建這個靜態(tài)節(jié)點,所以為了提升效率,在vue3中,它會把靜態(tài)節(jié)點進行提升,提升到render函數(shù)外面,這樣一來,這個靜態(tài)節(jié)點永遠只被創(chuàng)建一次,之后直接在render函數(shù)中使用就行了。
示例:
運行一個新創(chuàng)建的vue3項目,在控制臺可以清楚的看到,靜態(tài)節(jié)點被提升到外部了。這個就是靜態(tài)節(jié)點的提升。
其實不僅僅是靜態(tài)節(jié)點會進行提升,而且靜態(tài)屬性也是會提升的,ok,我們來看下:
示例:
這是vue3新創(chuàng)建項目中的APP.vue組件,加一條h1元素節(jié)點,要注意h1不是靜態(tài)節(jié)點,它是動態(tài)的,因為內(nèi)容是動態(tài)的,只有屬性是靜態(tài)的
//APP.vue代碼 <template><h1?class="active">{{name}}</h1><img?alt="Vue?logo"?src="./assets/logo.png"?/><HelloWorld?msg="解決bug的法醫(yī)"?/> </template><script> import?HelloWorld?from?'./components/HelloWorld.vue'export?default?{name:?'App',data(){return{name:"bobo"}},components:?{HelloWorld} } </script>效果如下:
???? 預(yù)字符串化
這一點真的是特別厲害,佩服尤大大,我們可以回憶下,在平時vue開發(fā)過程中,組件當(dāng)中沒有特別多的動態(tài)元素,大多都是靜態(tài)元素。
舉個栗子????:
<div?class="menu-bar-container"><div?class="logo"><h1>法醫(yī)</h1></div><ul?class="nav"><li><a?href="">menu</a></li><li><a?href="">menu</a></li><li><a?href="">menu</a></li><li><a?href="">menu</a></li><li><a?href="">menu</a></li></ul></div><div?class="user"><span>{{user.name}}</span></div>在這個組件中,除了span元素是動態(tài)元素之外,其余都是靜態(tài)節(jié)點,一般可以說是動靜比,動態(tài)內(nèi)容 / 靜態(tài)內(nèi)容,比例越小,靜態(tài)內(nèi)容越多,比例越大,動態(tài)內(nèi)容越多,vue3的編譯器它會非常智能地發(fā)現(xiàn)這一點,當(dāng)編譯器遇到大量連續(xù)的靜態(tài)內(nèi)容,會直接將它編譯為一個普通字符串節(jié)點,因為它知道這些內(nèi)容永遠不會變化,都是靜態(tài)節(jié)點。
???? 注意:必須是大量連續(xù)的靜態(tài)內(nèi)容才可以預(yù)字符串化哦,切記!目前是連續(xù)20個靜態(tài)節(jié)點才會預(yù)字符串化
然而在vue2中,每個元素都會變成虛擬節(jié)點,一大堆的虛擬節(jié)點????,這些全都是靜態(tài)節(jié)點,在vue3中它會智能地發(fā)現(xiàn)這一點
const?_hoisted_1?=?/*#__PURE__*/ //createStaticVNode?靜態(tài)節(jié)點的意思 _createStaticVNode("<div?class=\"menu-bar-container\"><div?class=\"logo\"><h1>法醫(yī)</h1></div><ul?class=\"nav\"><li><a?href=\"\">menu</a></li><li><a?href=\"\">menu</a></li><li><a?href=\"\">menu</a></li><li><a?href=\"\">menu</a></li><li><a?href=\"\">menu</a></li></ul></div>",?1)瞅個簡圖,感受一下vue3的魅力:
???? 緩存事件處理函數(shù)
舉個栗子????:
??<button?@click="count++">plus</button>對比處理方式:
//?vue2處理方式 render(ctx){return?createVNode("button",{onclick:function($event){ctx.count++;}}) }//vue3?處理方式 render(ctx,_cache){return?createVNode("button",{onclick:cache[0]?||?(cache[0]?=>($event)?=>(ctx.count++))}) }在vue2中創(chuàng)建一個虛擬節(jié)點button,屬性里面多了一個事件onclick,內(nèi)容就是count++
在vue3中就有緩存了,它認為這里的事件處理是不會變化的,不是說這次渲染是事件函數(shù),下次就變成別的了,于是vue3會智能地發(fā)現(xiàn)這一點,會做緩存處理,它首先會看一看緩存里面有沒有這個事件函數(shù),有的話直接返回,沒有的話就直接賦值為一個count++函數(shù),保證事件處理函數(shù)只生成一次,如下圖:
???? Block Tree
Block Tree 主要為了提高新舊兩棵樹在對比差異的時候提升效率,對比差異的過程叫diff算法,也叫patch算法。
vue2在對比新舊兩棵樹的時候,并不知道哪些節(jié)點是靜態(tài)的,哪些節(jié)點是動態(tài)的,因此只能一層一層比較,這就浪費了大部分時間在對比靜態(tài)節(jié)點上。
舉個栗子????:
<form><div><label>賬號:</label><input?v-model="user.loginId"?/></div><div><label>密碼:</label><input?v-model="user.loginPwd"?/></div> </form>vue2對比:
vue2通過一系列對比之后發(fā)現(xiàn),,只有input發(fā)生了變化,也就是黃色方塊部分,藍色方塊都為靜態(tài)節(jié)點,并沒有發(fā)生變化,這些沒有發(fā)生變化的對比都是一些沒有意義的對比,浪費了時間,浪費了生命
vue3對比:
vue3依托強大的編譯器,編譯器可以對每一個節(jié)點進行標(biāo)記,然后在根節(jié)點中記錄后代節(jié)點中哪些是動態(tài)節(jié)點,記錄之后,在對比的過程中它不是整棵樹進行對比,而是直接找到根節(jié)點,我們叫block節(jié)點,對比動態(tài)節(jié)點數(shù)組就可以了,這樣就會略過所有的靜態(tài)節(jié)點,也不涉及對樹的深度遍歷了,所以速度會非常快,當(dāng)靜態(tài)內(nèi)容越多,效率提升就越大。
當(dāng)然可能有小伙伴們會問,當(dāng)數(shù)據(jù)更新后可能會多出來分支,這樣處理的話會造成樹的不穩(wěn)定,樹一旦不穩(wěn)定就會出問題了,凡是樹不穩(wěn)定的地方vue3會把它全部變成塊block,具體還是挺復(fù)雜的,我還沒研究呢,大概就是這么個意思。等我想明白了,后面再跟大家說哈????
???? PatchFlag
vue3覺得在對比每一個節(jié)點的時候還是在浪費效率,盡管說已經(jīng)跳過了所有不需要比對的節(jié)點,但是它還要看看節(jié)點的元素類型、屬性以及遞歸子節(jié)點有沒有變化,在針對單個節(jié)點對比的時候進一步優(yōu)化,這依然需要依托vue3強大的編譯器,在編譯的時候,它會記錄哪個節(jié)點是動態(tài)內(nèi)容,并且做上標(biāo)記
舉個栗子????:
?<div?class="active"?title="法醫(yī)">{{user.name}}</div>vue3會在編譯的時候,它會對節(jié)點做上標(biāo)記,圖上標(biāo)記為1,表示在div節(jié)點中text是動態(tài)的
舉個栗子????:
<div?:class="active"?title="法醫(yī)">{{user.name}}</div>這個3表示在div節(jié)點中text和class類是動態(tài)的
???? 好了, 以上就是我的分享,希望能對大家有所幫助,歡迎大家在評論區(qū)討論鴨~
1. JavaScript 重溫系列(22篇全)
2. ECMAScript 重溫系列(10篇全)
3. JavaScript設(shè)計模式 重溫系列(9篇全)
4.?正則 / 框架 / 算法等 重溫系列(16篇全)
5.?Webpack4 入門(上)||?Webpack4 入門(下)
6.?MobX 入門(上)?||??MobX 入門(下)
7. 120+篇原創(chuàng)系列匯總
回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~
點擊“閱讀原文”查看 120+ 篇原創(chuàng)文章
總結(jié)
以上是生活随笔為你收集整理的【Vuejs】1017- Vue3 效率提升主要表现在哪些方面?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通c++【1033】
- 下一篇: 什么是图片的DPI?如何修改图片DPI值