Vue3為什么這么快
總所周知,程序員追求的就是一個(gè)字:快?。ó?dāng)然不是什么都追求快的,有些事情快起來(lái)是不行滴)
昨天Vue3.0正式發(fā)布了,激動(dòng)的心,顫抖的手,摸了摸我的頭發(fā),嗯~還好。
據(jù)說(shuō)Vue3.0相比Vue2.x在性能上提升了1.2~2倍,為啥他就這么快呢?
vue3.0做了以下事情
- diff算法優(yōu)化
- 靜態(tài)提升(hoistStatic)
- 事件偵聽(tīng)器緩存(cacheHandlers)
- SSR優(yōu)化(看心情更新)
diff算法優(yōu)化
Vue2.x的diff算法
vue2.x的diff算法叫做全量比較,顧名思義,就是當(dāng)數(shù)據(jù)改變的時(shí)候,會(huì)從頭到尾的進(jìn)行vDom對(duì)比,即使有些內(nèi)容是永恒固定不變的。
Vue3.0的diff算法
vue3.0的diff算法有個(gè)叫靜態(tài)標(biāo)記(PatchFlag)的小玩意,啥是靜態(tài)標(biāo)記呢?
簡(jiǎn)單點(diǎn)說(shuō),就是如果你的內(nèi)容會(huì)變,我會(huì)給你一個(gè)flag,下次數(shù)據(jù)更新的時(shí)候我直接來(lái)對(duì)比你,我就不對(duì)比那些沒(méi)有標(biāo)記的了
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, "'HelloWorld'"), _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) //上面這個(gè)1就是靜態(tài)標(biāo)記 ])) }
那么肯定有人又會(huì)問(wèn)了,為啥是個(gè)1呢?
TEXT = 1 // 動(dòng)態(tài)文本節(jié)點(diǎn) CLASS=1<<1,1 // 2//動(dòng)態(tài)class STYLE=1<<2,// 4 //動(dòng)態(tài)style PROPS=1<<3,// 8 //動(dòng)態(tài)屬性,但不包含類名和樣式 FULLPR0PS=1<<4,// 16 //具有動(dòng)態(tài)key屬性,當(dāng)key改變時(shí),需要進(jìn)行完整的diff比較。 HYDRATE_ EVENTS = 1 << 5,// 32 //帶有監(jiān)聽(tīng)事件的節(jié)點(diǎn) STABLE FRAGMENT = 1 << 6, // 64 //一個(gè)不會(huì)改變子節(jié)點(diǎn)順序的fragment KEYED_ FRAGMENT = 1 << 7, // 128 //帶有key屬性的fragment 或部分子字節(jié)有key UNKEYED FRAGMENT = 1<< 8, // 256 //子節(jié)點(diǎn)沒(méi)有key 的fragment NEED PATCH = 1 << 9, // 512 //一個(gè)節(jié)點(diǎn)只會(huì)進(jìn)行非props比較 DYNAMIC_SLOTS = 1 << 10 // 1024 // 動(dòng)態(tài)slot HOISTED = -1 // 靜態(tài)節(jié)點(diǎn) // 指示在diff算法中退出優(yōu)化模式 BALL = -2
靜態(tài)提升(hoistStatic)
Vue2.x中無(wú)論元素是否參與更新,每次都會(huì)重新創(chuàng)建然后渲染
Vue3.0中對(duì)不參與更新的元素,會(huì)做靜態(tài)提升,只會(huì)被創(chuàng)建一次,在渲染時(shí)直接復(fù)用即可
還是這段熟悉的代碼,開(kāi)啟靜態(tài)提升前
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("p", null, "'HelloWorld'"), _createVNode("p", null, "'HelloWorld'"), _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }
開(kāi)啟靜態(tài)提升后編譯結(jié)果
const _hoisted_1 = /*#__PURE__*/_createVNode("p", null, "'HelloWorld'", -1 /* HOISTED */) const _hoisted_2 = /*#__PURE__*/_createVNode("p", null, "'HelloWorld'", -1 /* HOISTED */) export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _hoisted_1, _hoisted_2, _createVNode("p", null, _toDisplayString(_ctx.msg), 1 /* TEXT */) ])) }
可以看到開(kāi)啟了靜態(tài)提升后,直接將那兩個(gè)內(nèi)容為helloworld的p標(biāo)簽聲明在外面了,直接就拿來(lái)用了,這么搞的話那肯定會(huì)快啊
事件偵聽(tīng)器緩存
默認(rèn)情況下onClick會(huì)被視為動(dòng)態(tài)綁定,所以每次都會(huì)去追蹤它的變化
但是因?yàn)槭峭粋€(gè)函數(shù),所以沒(méi)有追蹤變化,直接緩存起來(lái)復(fù)用即可
dom結(jié)構(gòu)
<div> <button @click = 'onClick'>點(diǎn)我</button> </div>
開(kāi)啟事件偵聽(tīng)器緩存之前:
export const render = /*#__PURE__*/_withId(function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _ctx.onClick }, "點(diǎn)我", 8 /* PROPS */, ["onClick"]) // PROPS=1<<3,// 8 //動(dòng)態(tài)屬性,但不包含類名和樣式 ])) })
這里有一個(gè)8,表示著這個(gè)節(jié)點(diǎn)有了靜態(tài)標(biāo)記,有靜態(tài)標(biāo)記就會(huì)進(jìn)行diff算法對(duì)比差異,所以會(huì)浪費(fèi)時(shí)間
開(kāi)啟事件偵聽(tīng)器緩存之后:
export function render(_ctx, _cache, $props, $setup, $data, $options) { return (_openBlock(), _createBlock("div", null, [ _createVNode("button", { onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.onClick(...args))) }, "點(diǎn)我") ])) }
可以發(fā)現(xiàn),開(kāi)啟事件偵聽(tīng)器緩存后,沒(méi)有靜態(tài)標(biāo)記了,這就快了好多嘛
到此這篇關(guān)于Vue3為什么這么快的文章就介紹到這了,更多相關(guān)Vue3 快內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Vue-cli 創(chuàng)建的項(xiàng)目如何跨域請(qǐng)求
本篇文章主要介紹了詳解Vue-cli 創(chuàng)建的項(xiàng)目如何跨域請(qǐng)求 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05vue中transition組件在項(xiàng)目中運(yùn)用小結(jié)
這篇文章主要介紹了vue中transition組件在項(xiàng)目中運(yùn)用,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12vue spa應(yīng)用中的路由緩存問(wèn)題與解決方案
這篇文章主要介紹了vue spa應(yīng)用中的路由緩存問(wèn)題與解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05vue.js實(shí)現(xiàn)的綁定class操作示例
這篇文章主要介紹了vue.js實(shí)現(xiàn)的綁定class操作,結(jié)合實(shí)例形式分析了vue.js綁定class常見(jiàn)的3種操作技巧,需要的朋友可以參考下2018-07-07Vue.js中自定義Markdown插件實(shí)現(xiàn)References解析(推薦)
本文主要寫的是,如何編寫一個(gè)插件來(lái)解析<references>標(biāo)簽,并將其轉(zhuǎn)換為HTML,這種方法可以應(yīng)用于其他自定義標(biāo)簽和功能,為Vue.js應(yīng)用程序中的Markdown渲染提供了極大的靈活性,感興趣的朋友跟隨小編一起看看吧2024-07-07vue3中處理不同數(shù)據(jù)結(jié)構(gòu)JSON的實(shí)現(xiàn)
本文主要介紹了vue3中處理不同數(shù)據(jù)結(jié)構(gòu)JSON的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06elementui?Select選擇器嵌套tree實(shí)現(xiàn)TreeSelect方式
這篇文章主要介紹了elementui?Select選擇器嵌套tree實(shí)現(xiàn)TreeSelect方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10VUE在線調(diào)用阿里Iconfont圖標(biāo)庫(kù)的方法
這篇文章主要介紹了VUE在線調(diào)用阿里Iconfont圖標(biāo)庫(kù)的方法,內(nèi)容是圍繞VUE前端和阿里Iconfont圖標(biāo)庫(kù)展開(kāi)的,經(jīng)歷了從網(wǎng)站上東拼西湊圖標(biāo)的時(shí)代,大概是15~16年左右我開(kāi)始解除阿里Iconfont圖標(biāo)庫(kù),剛開(kāi)始就只會(huì)下載圖標(biāo)使用,需要的朋友可以參考下2021-10-10$router.push()中通過(guò)path跳轉(zhuǎn)和通過(guò)name跳轉(zhuǎn)區(qū)別解析
今天在路由跳轉(zhuǎn)傳參時(shí)發(fā)現(xiàn)params傳參接收到的總是為空,才發(fā)現(xiàn)通過(guò)path和name傳參是有區(qū)別的,這篇文章主要介紹了$router.push()中通過(guò)path跳轉(zhuǎn)和通過(guò)name跳轉(zhuǎn)有什么區(qū)別,需要的朋友可以參考下2023-11-11