Vue 3-0 到底怎麼變快?
作者:快跑啊小盧_
juejin.cn/post/6979039113689169957
前言🖖
自從Vue3.0
發佈後一直想要學習一下新特性,誰曾想到一直鴿到了現在。面對前端行業不學習就被淘汰的內卷環境什麼都要學起來呀,學的時候索性記錄總結一下。
Vue 3.0 亮點🤩
-
Vue 3.0
性能比Vue 2.x
快 1.2~2 倍 -
Tree-Shaking
:按需編譯,體積比Vue 2.x
小 -
新推出的
Composition API
使組件更易維護 -
更好
TypeScript
支持 -
Custom Render API
:暴露了自定義渲染API
-
更多先進牛逼的組件
總的來說就是更快更小更舒服
Vue 3.0 到底是如何變快🤔
大家都說Vue 3.0
變快了,那他到底是哪裏快了呢?做了哪些優化纔會讓它有這種效果?
diff 算法優化🦄
-
熟悉
Vue 2.x
的兄弟都知道渲染真實DOM
的開銷是很大的,比如我們修改某個數據直接渲染在真實DOM
上會引起DOM
樹的重排重繪。 -
於是就有了
diff
算法可以根據真實DOM
生成一棵虛擬DOM
樹(Virtual DOM
)從而計算出Virtual DOM
中被改變的部分,然後針對該部分進行原生DOM
操作,而不用重新渲染整個頁面。 -
值得注意的是
diff
算法是對樹的每一層進行遍歷從而找出不同進行替換(圖片來自網絡),而Vue3.0
的diff
算法就在此做出了優化。 -
舉個例子說明一下吧, 在下面有兩個
p
標籤一個是不會變的數據一個是綁定的數據,當sth
改變的時候,Vue
會生成新的虛擬DOM
然後和舊的進行對比。
<div>
<p>hi 小盧!!</p>
<p>{{sth}}</p>
</div>
在Vue 2.x
中
在Vue 3.0
中
-
從上面的圖例可知在
Vue 2.x
中diff
算法會將兩棵DOM
樹的所有節點進行對比,但實際變化的只有雙向綁定的那個。 -
在
Vue 3.0
中會在創建虛擬DOM
的時候將會變化的內容進行靜態標記,這樣diff
算法的時候直接對比有標記的,對比的少了自然而然速度就變快了。
在 Vue 3 Template Explorer 中顯示如下
flag
的 1 是Patchflag
枚舉, 取值爲 1 代表這個元素的文本是動態綁定的
附錄:PatchFlags
export const enum PatchFlags {Ⅰ
TEXT = 1,1/動態文本節點
CLASS = 1<<1,1/ 2// 動態 classSTYLE= 1<<2,// 4//動態 style
PROPS = 1<< 3,// 8// 動態屬性,但不包含類名和樣式
FULL_PROPS = 1<<4,// 16 //具有動態 key屬性,當key改變時,需要進行完整的 diff 比較。
HYDRATE_EVENTS = 1<<5,// 32//帶有監聽事件的節點
STABLE_FRAGMENT = 1<<6,// 64//一個不會改變子節點順序的 fragment
KEYED_FRAGMENT = 1<<7,// 128//帶有key屬性的 fragment 或部分子字節有
keyUNKEYED_FRAGMENT = 1<<8,// 256//子節點沒有key 的 fragment
NEED_ PATCH =1<<9,//512//一個節點只會進行非 props比較
DYNAMIC_SLOTS = 1 << 10,//1024 // 動態的插槽
// SPECIAL FLAGS (下面是特殊的)---------------------------------------------------------
// 以下是特殊的flag,不會在優化中被用到,是內置的特殊flag
// 表示他是靜態節點,他的內容永遠不會改變,對於hydrate的過程中,不會需要再對其子節點進行diff
HOISTED = -1,
BAIL = -2, // 用來表示一個節點的diff應該結束
}
hoistStatic(靜態提升)🦓
-
這就好比你每天去便利店買咖啡,每次買的時候店員都問你需要什麼,當時間久了店員熟悉了你的習慣就省去了店員問你'要什麼'的這個過程,直接給你所需要的商品。
-
顧名思義
靜態提升
就是把不參與更新的靜態元素給提升出來,說白了就是類似把變量變成常量不進行重新創建
。 -
在
Vue 2.x
中無論元素是否參與更新每次都會重新創建,然後渲染, 這對於性能肯定是會有些許損耗。
舉個例子說明一下
<div>
<div>Hello Vue3.0</div>
<div>hi 小盧!</div>
<p>{{sth}}</p>
</div>
未使用靜態提升
使用靜態提升
-
從上面的兩幅對比圖可以明顯的看到
未使用靜態提升
的變量會放在render
函數里面,每次更新數據都會重新創建並渲染出來 -
而
使用了靜態提升
的元素會被提取出來放在render
函數外面,這樣下次更新的時候就不會把這個元素重新創建,創建的元素少了,自然而然速度也就快起來了。 -
Vue 3.0
中就是啓用了靜態提升
把不需要更新的元素放到外面只創建一次,在渲染的時候直接複用即可。
cacheHandlers(事件偵聽器緩存)🐲
-
從上面的
diff
算法優化中我們知道,根據PatchFlags
會把動態綁定的元素加上靜態標記,那一個事件函數自然就會被加上靜態標記,在diff
中會將有標記的元素進行對比來更新數據。 -
如果我們用的這個函數從頭到尾都沒有改變過,那是不是也可以讓它像靜態元素一樣不進行對比呢?
-
那我都這麼問了答案肯定是:可以的!
-
顧名思義事件偵聽器緩存就是把沒有改變過的事件給偵聽到了,然後緩存。
-
就好比剛學
Vue
的你不懂各種api
和優秀的組件,每次用到的時候都會去查看看怎麼做,但是當你做久了之後自然你就熟能生巧了,沒有得到消息說api
更新了,自然就不會去查找文檔對比有什麼差異。
舉個例子說明一下
<div>
<div>Hello Vue3.0</div>
<div>hi 小盧!</div>
<p>{{sth}}</p>
<div @click="doSthing">我是一個點擊事件</div>
</div>
未使用事件偵聽器緩存
使用事件偵聽器緩存
-
上面轉換過的代碼如果看不懂的話沒有關係,我們只需要觀察它是否有靜態標記即可。
-
從上面兩幅對比圖可以看出來在使用了事件監聽器緩存的情況下它的靜態標記
8
消失了,就說明在Vue 3.0
在每次數據更新時不會對它進行對比了,對比的少了自然而然速度也就加快了
寫在最後👌
-
以上就是
Vue 3.0
變快做的一些優化。 -
總的來說
Vue 3.0
通過優化diff
算法讓該對比的進行對比,不該對比的不進行對比。 -
通過靜態提升和事件偵聽緩存來減少不變的元素創建的頻率,
加快了
運行速度。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/lsjrWQTgl23TDxcwpdfWDA