久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

vue3編譯做了哪些優(yōu)化

vue3編譯優(yōu)化有:1、引入了 patchFlag,用來標(biāo)記動(dòng)態(tài)內(nèi)容;在編譯過程中會(huì)根據(jù)不同的屬性類型打上不同的標(biāo)識(shí),從而實(shí)現(xiàn)了快速diff算法。2、Block Tree。3、靜態(tài)提升,是將靜態(tài)的節(jié)點(diǎn)或者屬性提升出去。4、預(yù)解析字符串化,當(dāng)連續(xù)靜態(tài)節(jié)點(diǎn)超過10個(gè)時(shí),會(huì)將靜態(tài)節(jié)點(diǎn)序列化為字符串。5、函數(shù)緩存;開啟cacheHandlers選項(xiàng)后,函數(shù)會(huì)被緩存起來,后續(xù)可直接使用。

vue3編譯做了哪些優(yōu)化

本教程操作環(huán)境:windows7系統(tǒng)、vue3版,DELL G3電腦。

本文主要來分析 Vue3.0 編譯階段做的優(yōu)化,在 patch 階段是如何利用這些優(yōu)化策略來減少比對(duì)次數(shù)。 由于組件更新時(shí)依然需要遍歷該組件的整個(gè) vnode 樹,比如下面這個(gè)模板:

<template>   <div id="container">     <p class="text">static text</p>     <p class="text">static text</p>     <p class="text">{{ message }}</p>     <p class="text">static text</p>     <p class="text">static text</p>   </div> </template>
登錄后復(fù)制

整個(gè) diff 過程如圖所示:

vue3編譯做了哪些優(yōu)化

可以看到,因?yàn)檫@段代碼中只有一個(gè)動(dòng)態(tài)節(jié)點(diǎn),所以這里有很多 diff 和遍歷其實(shí)都是不需要的,這就會(huì)導(dǎo)致 vnode 的性能跟模版大小正相關(guān),跟動(dòng)態(tài)節(jié)點(diǎn)的數(shù)量無關(guān),當(dāng)一些組件的整個(gè)模版內(nèi)只有少量動(dòng)態(tài)節(jié)點(diǎn)時(shí),這些遍歷都是性能的浪費(fèi)。對(duì)于上述例子,理想狀態(tài)只需要 diff 這個(gè)綁定 message 動(dòng)態(tài)節(jié)點(diǎn)的 p 標(biāo)簽即可。

Vue.js 3.0 通過編譯階段對(duì)靜態(tài)模板的分析,編譯生成了 Block tree

Block tree 是一個(gè)將模板基于動(dòng)態(tài)節(jié)點(diǎn)指令切割的嵌套區(qū)塊,每個(gè)區(qū)塊內(nèi)部的節(jié)點(diǎn)結(jié)構(gòu)是固定的,而且每個(gè)區(qū)塊只需要以一個(gè) Array 來追蹤自身包含的動(dòng)態(tài)節(jié)點(diǎn)。借助 Block treeVue.js 將 vnode 更新性能由與模版整體大小相關(guān)提升為與動(dòng)態(tài)內(nèi)容的數(shù)量相關(guān),這是一個(gè)非常大的性能突破。

PatchFlag

由于 diff 算法無法避免新舊虛擬 DOM 中無用的比較操作,Vue.js 3.0 引入了 patchFlag,用來標(biāo)記動(dòng)態(tài)內(nèi)容。在編譯過程中會(huì)根據(jù)不同的屬性類型打上不同的標(biāo)識(shí),從而實(shí)現(xiàn)了快速 diff 算法。PatchFlags 的所有枚舉類型如下所示:

export const enum PatchFlags {   TEXT = 1, // 動(dòng)態(tài)文本節(jié)點(diǎn)   CLASS = 1 << 1, // 動(dòng)態(tài)class   STYLE = 1 << 2, // 動(dòng)態(tài)style   PROPS = 1 << 3, // 除了class、style動(dòng)態(tài)屬性   FULL_PROPS = 1 << 4, // 有key,需要完整diff   HYDRATE_EVENTS = 1 << 5, // 掛載過事件的   STABLE_FRAGMENT = 1 << 6, // 穩(wěn)定序列,子節(jié)點(diǎn)順序不會(huì)發(fā)生變化   KEYED_FRAGMENT = 1 << 7, // 子節(jié)點(diǎn)有key的fragment   UNKEYED_FRAGMENT = 1 << 8, // 子節(jié)點(diǎn)沒有key的fragment   NEED_PATCH = 1 << 9, // 進(jìn)行非props比較, ref比較   DYNAMIC_SLOTS = 1 << 10, // 動(dòng)態(tài)插槽   DEV_ROOT_FRAGMENT = 1 << 11,    HOISTED = -1, // 表示靜態(tài)節(jié)點(diǎn),內(nèi)容變化,不比較兒子   BAIL = -2 // 表示diff算法應(yīng)該結(jié)束 }
登錄后復(fù)制

Block Tree

vue3編譯做了哪些優(yōu)化

左側(cè)的 template 經(jīng)過編譯后會(huì)生成右側(cè)的 render 函數(shù),里面有 _openBlock_createElementBlock_toDisplayString_createElementVNode(createVnode) 等輔助函數(shù)。

let currentBlock = null function _openBlock() {   currentBlock = [] // 用一個(gè)數(shù)組來收集多個(gè)動(dòng)態(tài)節(jié)點(diǎn) } function _createElementBlock(type, props, children, patchFlag) {   return setupBlock(createVnode(type, props, children, patchFlag)); }  export function createVnode(type, props, children = null, patchFlag = 0) {   const vnode = {     type,     props,     children,     el: null, // 虛擬節(jié)點(diǎn)上對(duì)應(yīng)的真實(shí)節(jié)點(diǎn),后續(xù)diff算法     key: props?.["key"],     __v_isVnode: true,     shapeFlag,     patchFlag    };   ...    if (currentBlock && vnode.patchFlag > 0) {     currentBlock.push(vnode);   }   return vnode; }  function setupBlock(vnode) {   vnode.dynamicChildren = currentBlock;   currentBlock = null;   return vnode; }  function _toDisplayString(val) {   return isString(val)     ? val     : val == null     ? ""     : isObject(val)     ? JSON.stringify(val)     : String(val); }
登錄后復(fù)制

此時(shí)生成的 vnode 如下:

vue3編譯做了哪些優(yōu)化

此時(shí)生成的虛擬節(jié)點(diǎn)多出一個(gè) dynamicChildren 屬性,里面收集了動(dòng)態(tài)節(jié)點(diǎn) span

節(jié)點(diǎn) diff 優(yōu)化策略:

我們之前分析過,在 patch 階段更新節(jié)點(diǎn)元素的時(shí)候,會(huì)執(zhí)行 patchElement 函數(shù),我們?cè)賮砘仡櫼幌滤膶?shí)現(xiàn):

const patchElement = (n1, n2) => { // 先復(fù)用節(jié)點(diǎn)、在比較屬性、在比較兒子   let el = n2.el = n1.el;   let oldProps = n1.props || {}; // 對(duì)象   let newProps = n2.props || {}; // 對(duì)象   patchProps(oldProps, newProps, el);    if (n2.dynamicChildren) { // 只比較動(dòng)態(tài)元素     patchBlockChildren(n1, n2);   } else {     patchChildren(n1, n2, el); // 全量 diff   } }
登錄后復(fù)制

我們?cè)谇懊娼M件更新的章節(jié)分析過這個(gè)流程,在分析子節(jié)點(diǎn)更新的部分,當(dāng)時(shí)并沒有考慮到優(yōu)化的場景,所以只分析了全量比對(duì)更新的場景。

而實(shí)際上,如果這個(gè) vnode 是一個(gè) Block vnode,那么我們不用去通過 patchChildren 全量比對(duì),只需要通過 patchBlockChildren 去比對(duì)并更新 Block 中的動(dòng)態(tài)子節(jié)點(diǎn)即可。 由此可以看出性能被大幅度提升,從 tree 級(jí)別的比對(duì),變成了線性結(jié)構(gòu)比對(duì)。

我們來看一下它的實(shí)現(xiàn):

const patchBlockChildren = (n1, n2) => {   for (let i = 0; i < n2.dynamicChildren.length; i++) {     patchElement(n1.dynamicChildren[i], n2.dynamicChildren[i])   } }
登錄后復(fù)制

屬性 diff 優(yōu)化策略:

接下來我們看一下屬性比對(duì)的優(yōu)化策略:

const patchElement = (n1, n2) => { // 先復(fù)用節(jié)點(diǎn)、在比較屬性、在比較兒子   let el = n2.el = n1.el;   let oldProps = n1.props || {}; // 對(duì)象   let newProps = n2.props || {}; // 對(duì)象   let { patchFlag, dynamicChildren } = n2      if (patchFlag > 0) {     if (patchFlag & PatchFlags.FULL_PROPS) { // 對(duì)所 props 都進(jìn)行比較更新       patchProps(el, n2, oldProps, newProps, ...)     } else {       // 存在動(dòng)態(tài) class 屬性時(shí)       if (patchFlag & PatchFlags.CLASS) {         if (oldProps.class !== newProps.class) {           hostPatchProp(el, 'class', null, newProps.class, ...)         }       }       // 存在動(dòng)態(tài) style 屬性時(shí)       if (patchFlag & PatchFlags.STYLE) {         hostPatchProp(el, 'style', oldProps.style, newProps.style, ...)       }              // 針對(duì)除了 style、class 的 props       if (patchFlag & PatchFlags.PROPS) {         const propsToUpdate = n2.dynamicProps!         for (let i = 0; i < propsToUpdate.length; i++) {           const key = propsToUpdate[i]           const prev = oldProps[key]           const next = newProps[key]           if (next !== prev) {             hostPatchProp(el, key, prev, next, ...)           }         }       }       if (patchFlag & PatchFlags.TEXT) { // 存在動(dòng)態(tài)文本         if (n1.children !== n2.children) {           hostSetElementText(el, n2.children as string)         }       }      } else if (dynamicChildren == null) {       patchProps(el, n2, oldProps, newProps, ...)     }   } }  function hostPatchProp(el, key, prevValue, nextValue) {   if (key === 'class') { // 更新 class      patchClass(el, nextValue)   } else if (key === 'style') { // 更新 style     patchStyle(el, prevValue, nextValue)   } else if (/^on[^a-z]/.test(key)) {  // events  addEventListener     patchEvent(el, key, nextValue);   } else { // 普通屬性 el.setAttribute     patchAttr(el, key, nextValue);   } }  function patchClass(el, nextValue) {   if (nextValue == null) {     el.removeAttribute('class'); // 如果不需要class直接移除   } else {     el.className = nextValue   } }  function patchStyle(el, prevValue, nextValue = {}){   ... }  function patchAttr(el, key, nextValue){   ... }
登錄后復(fù)制

總結(jié): vue3 會(huì)充分利用 patchFlagdynamicChildren 做優(yōu)化。如果確定只是某個(gè)局部的變動(dòng),比如 style 改變,那么只會(huì)調(diào)用 hostPatchProp 并傳入對(duì)應(yīng)的參數(shù) style 做特定的更新(靶向更新);如果有 dynamicChildren,會(huì)執(zhí)行 patchBlockChildren 做對(duì)比更新,不會(huì)每次都對(duì) props 和子節(jié)點(diǎn)進(jìn)行全量的對(duì)比更新。圖解如下:

vue3編譯做了哪些優(yōu)化

靜態(tài)提升

靜態(tài)提升是將靜態(tài)的節(jié)點(diǎn)或者屬性提升出去,假設(shè)有以下模板:

<div>   <span>hello</span>    <span a=1 b=2>{{name}}</span>   <a><span>{{age}}</span></a> </div>
登錄后復(fù)制

編譯生成的 render 函數(shù)如下:

export function render(_ctx, _cache, $props, $setup, $data, $options) {   return (_openBlock(), _createElementBlock("div", null, [     _createElementVNode("span", null, "hello"),     _createElementVNode("span", {       a: "1",       b: "2"     }, _toDisplayString(_ctx.name), 1 /* TEXT */),     _createElementVNode("a", null, [       _createElementVNode("span", null, _toDisplayString(_ctx.age), 1 /* TEXT */)     ])   ])) }
登錄后復(fù)制

我們把模板編譯成 render 函數(shù)是這個(gè)醬紫的,那么問題就是每次調(diào)用 render 函數(shù)都要重新創(chuàng)建虛擬節(jié)點(diǎn)。

開啟靜態(tài)提升 hoistStatic 選項(xiàng)后

const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", null, "hello", -1 /* HOISTED */) const _hoisted_2 = {   a: "1",   b: "2" }  export function render(_ctx, _cache, $props, $setup, $data, $options) {   return (_openBlock(), _createElementBlock("div", null, [     _hoisted_1,     _createElementVNode("span", _hoisted_2, _toDisplayString(_ctx.name), 1 /* TEXT */),     _createElementVNode("a", null, [       _createElementVNode("span", null, _toDisplayString(_ctx.age), 1 /* TEXT */)     ])   ])) }
登錄后復(fù)制

預(yù)解析字符串化

靜態(tài)提升的節(jié)點(diǎn)都是靜態(tài)的,我們可以將提升出來的節(jié)點(diǎn)字符串化。 當(dāng)連續(xù)靜態(tài)節(jié)點(diǎn)超過 10 個(gè)時(shí),會(huì)將靜態(tài)節(jié)點(diǎn)序列化為字符串。

假如有如下模板:

<div>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span>   <span>static</span> </div>
登錄后復(fù)制

開啟靜態(tài)提升 hoistStatic 選項(xiàng)后

const _hoisted_1 = /*#__PURE__*/_createStaticVNode("<span>static</span><span>static</span><span>static</span><span>static</span><span>static</span><span>static</span><span>static</span><span>static</span><span>static</span><span>static</span>", 10) const _hoisted_11 = [  _hoisted_1]  export function render(_ctx, _cache, $props, $setup, $data, $options) {   return (_openBlock(), _createElementBlock("div", null, _hoisted_11)) }
登錄后復(fù)制

函數(shù)緩存

假如有如下模板:

<div @click="event => v = event.target.value"></div>
登錄后復(fù)制

編譯后:

const _hoisted_1 = ["onClick"]  export function render(_ctx, _cache, $props, $setup, $data, $options) {   return (_openBlock(), _createElementBlock("div", {     onClick: event => _ctx.v = event.target.value   }, null, 8 /* PROPS */, _hoisted_1)) }
登錄后復(fù)制

每次調(diào)用 render 的時(shí)候要?jiǎng)?chuàng)建新函數(shù),開啟函數(shù)緩存 cacheHandlers 選項(xiàng)后,函數(shù)會(huì)被緩存起來,后續(xù)可以直接使用

export function render(_ctx, _cache, $props, $setup, $data, $options) {   return (_openBlock(), _createElementBlock("div", {     onClick: _cache[0] || (_cache[0] = event => _ctx.v = event.target.value)   })) }
登錄后復(fù)制

總結(jié)

以上幾點(diǎn)即為 Vuejs 在編譯階段做的優(yōu)化,基于上面幾點(diǎn),Vuejspatch 過程中極大地提高了性能。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
成人小电影网站| 国产精品久久久久av蜜臀| 亚洲tv在线| 国产精品久久观看| 青青草视频一区| 羞羞答答国产精品www一本| 日韩激情一区| 国产精品一区二区美女视频免费看 | 鲁大师影院一区二区三区| 久久一区国产| 奇米狠狠一区二区三区| 日韩一级欧洲| 91视频精品| 亚洲二区视频| 日本欧美不卡| av最新在线| 精品一区二区三区亚洲| 国产91在线精品| 国产精品久久久久久模特| 日韩精品高清不卡| 免费精品视频在线| 青青草国产精品亚洲专区无| 亚洲精品亚洲人成在线观看| 国产美女一区| 亚洲专区视频| 免费看黄色91| 亚洲精品影视| 日本在线视频一区二区| 99视频一区| 日本在线不卡视频一二三区| 蜜桃久久久久久久| 亚洲69av| 国产香蕉精品| 鲁鲁在线中文| 欧美精选视频一区二区| 麻豆mv在线观看| 精精国产xxxx视频在线野外| 夜久久久久久| 亚洲精品激情| 午夜亚洲福利| 日韩欧美中文字幕在线视频| 韩国女主播一区二区三区| 久久99视频| 高清一区二区三区av| 伊人久久在线| 综合色就爱涩涩涩综合婷婷| 日韩精品社区| 欧美日韩18| 捆绑调教美女网站视频一区| 日韩视频网站在线观看| 色婷婷精品视频| 99视频一区| 日韩一区中文| 日韩av专区| 偷拍精品精品一区二区三区| 国产综合色产| 亚州精品视频| 蜜臀av亚洲一区中文字幕| 日韩三级视频| 红杏一区二区三区| 免费精品国产的网站免费观看| 亚洲精品日本| 欧美激情在线精品一区二区三区| 高清久久一区| 午夜久久福利| 悠悠资源网久久精品| 国产色噜噜噜91在线精品| 国产伊人久久| 欧美a级一区| 亚洲激情五月| 国产精品亚洲四区在线观看| 色在线中文字幕| 丝袜美腿高跟呻吟高潮一区| 91亚洲精品在看在线观看高清| 神马午夜久久| 日韩毛片网站| 中文字幕高清在线播放| 亚洲中午字幕| 国产亚洲一区二区手机在线观看 | 欧美日韩伊人| 97精品一区| 日韩在线一二三区| 日韩av首页| 久久高清国产| 国产精品va视频| 亚洲大全视频| 久久精品免费看| 美女网站一区| 免费日韩成人| 天堂成人国产精品一区| 久久久久久一区二区| 视频在线观看一区| 欧美日韩视频免费观看| 你懂的国产精品| 视频一区中文字幕精品| 99pao成人国产永久免费视频| 中文字幕人成乱码在线观看| 国产精品伊人| 蘑菇福利视频一区播放| 特黄毛片在线观看| 国产精品igao视频网网址不卡日韩| 免费精品视频| 欧美精品激情| 激情婷婷欧美| 午夜av成人| av在线最新| 久久精品人人| 国产精品va视频| 欧美在线黄色| 日韩亚洲精品在线观看| 丝袜脚交一区二区| 午夜欧美视频| 91成人网在线观看| 精品丝袜在线| 日本免费一区二区三区四区| 高清久久一区| 麻豆91小视频| 国产精品www.| 欧美激情99| 精品一区视频| 激情久久一区二区| 久久免费影院| 精品日本视频| 精品国产午夜肉伦伦影院| 麻豆国产一区| 精品国产乱码| 日韩av有码| av资源中文在线天堂| 久久三级中文| 福利一区和二区| av综合电影网站| 日韩欧美一区二区三区在线观看| 午夜久久中文| 91精品国产调教在线观看| 国产一区久久| 快she精品国产999| 日韩中文av| 国产欧美日韩影院| 韩国一区二区三区视频| 美女av在线免费看| 久久精品影视| 日韩视频在线一区二区三区 | a日韩av网址| 久久精品国产www456c0m| 欧美美女一区| 天堂va欧美ⅴa亚洲va一国产| 国产乱人伦精品一区| 高清久久一区| se01亚洲视频| 欧美成人高清| 蜜臀91精品一区二区三区| 日本99精品| 精品一区av| 亚洲二区免费| 亚洲精品极品| 国产精品美女在线观看直播| 91日韩在线| 亚洲一区区二区| 国产调教精品| 一本大道色婷婷在线| 六月婷婷一区| 国产精品久久久久久久久免费高清 | 成人美女视频| 亚洲精品网址| 蜜臀久久久久久久| 国产精品高清一区二区| 天堂中文av在线资源库| 99国产精品久久久久久久| 天堂va在线高清一区| 久久伊人久久| 在线日韩欧美| 日韩激情网站| 国产精品国产一区| 不卡在线一区二区| 日本欧美在线| 日本精品不卡| 日韩精品亚洲aⅴ在线影院| 视频在线不卡免费观看| 狠狠色狠狠色综合日日tαg| 国产欧美综合一区二区三区| 99久久99视频只有精品| 少妇精品在线| 神马久久午夜| 视频一区中文字幕精品| 91亚洲国产| 日韩三级精品| 亚洲国产影院| 国产极品嫩模在线观看91精品| 久久理论电影| 日本91福利区| 99久久久久国产精品| 日韩av中文字幕一区二区| 日韩高清中文字幕一区二区| 日韩精品a在线观看91| 四虎影视精品| 国产精品久久| 久久国产成人| av综合电影网站| 久久国产三级| 久久久水蜜桃av免费网站|