最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue編譯器optimize源碼分析

 更新時(shí)間:2022年07月13日 11:31:08   作者:李李  
這篇文章主要為大家介紹了Vue?編譯器optimize源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

接上文 parseHTML 函數(shù)源碼解析 chars、end、comment鉤子函數(shù)

上一章節(jié)我們講到通過解析將template轉(zhuǎn)成AST(抽象語法樹),接下來繼續(xù)對模型樹優(yōu)化,進(jìn)行靜態(tài)標(biāo)注。那么問題來了,什么是靜態(tài)標(biāo)注?為什么要靜態(tài)標(biāo)注。

在源碼的注釋中我們找到了下面這段話:

/**
 * Goal of the optimizer: walk the generated template AST tree
 * and detect sub-trees that are purely static, i.e. parts of
 * the DOM that never needs to change.
 *
 * Once we detect these sub-trees, we can:
 *
 * 1. Hoist them into constants, so that we no longer need to
 *    create fresh nodes for them on each re-render;
 * 2. Completely skip them in the patching process.
 */
  • 永遠(yuǎn)不需要變化的DOM就是靜態(tài)的。
  • 重新渲染時(shí),作為常量,無需創(chuàng)建新節(jié)點(diǎn);

optimize 源碼之旅

function optimize(root, options) {
	if (!root) {
		return
	}
	isStaticKey = genStaticKeysCached(options.staticKeys || '');
	isPlatformReservedTag = options.isReservedTag || no;
	// first pass: mark all non-static nodes.
	markStatic$1(root);
	// second pass: mark static roots.
	markStaticRoots(root, false);
}

可以看到源碼并不復(fù)雜初始定義了兩個(gè)變量。

  • isStaticKey 獲取 genStaticKeysCached函數(shù)返回值, 獲取 makeMap (點(diǎn)此查看) 函數(shù)返回值引用 。
  • isPlatformReservedTag 獲取編譯器選項(xiàng) isReservedTag 的引用,檢查給定的字符是否是保留的標(biāo)簽。

接下來就是兩個(gè)重要的方法 markStatic$1 標(biāo)注靜態(tài)節(jié)點(diǎn)、markStaticRoots 標(biāo)注靜態(tài)根節(jié)點(diǎn),我們先來看下 markStatic$1的源碼。

markStatic$1源碼

function markStatic$1(node) {
	node.static = isStatic(node);
	if (node.type === 1) {
		// do not make component slot content static. this avoids
		// 1. components not able to mutate slot nodes
		// 2. static slot content fails for hot-reloading
		if (
			!isPlatformReservedTag(node.tag) &&
			node.tag !== 'slot' &&
			node.attrsMap['inline-template'] == null
		) {
			return
		}
		for (var i = 0, l = node.children.length; i < l; i++) {
			var child = node.children[i];
			markStatic$1(child);
			if (!child.static) {
				node.static = false;
			}
		}
		if (node.ifConditions) {
			for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
				var block = node.ifConditions[i$1].block;
				markStatic$1(block);
				if (!block.static) {
					node.static = false;
				}
			}
		}
	}
}

第一步判斷節(jié)點(diǎn)狀態(tài)并標(biāo)注。

node.static = isStatic(node);
在這給元素描述對象(AST) 擴(kuò)展了static屬性,通過isStatic方法調(diào)用后返回值,確認(rèn)哪些節(jié)點(diǎn)是靜態(tài)的,哪些是動態(tài)的。

isStatic源碼

function isStatic(node) {
	if (node.type === 2) { // expression
		return false
	}
	if (node.type === 3) { // text
		return true
	}
	return !!(node.pre || (
		!node.hasBindings && // no dynamic bindings
		!node.if && !node.for && // not v-if or v-for or v-else
		!isBuiltInTag(node.tag) && // not a built-in
		isPlatformReservedTag(node.tag) && // not a component
		!isDirectChildOfTemplateFor(node) &&
		Object.keys(node).every(isStaticKey)
	))
}

在這判斷node.type的值為2,表示為表達(dá)式返回false,node.type的值為3,表示為靜態(tài)文本返回 true 總結(jié):節(jié)點(diǎn)類型為表達(dá)式,標(biāo)注為非靜態(tài);普通文本為靜態(tài)。

上面的很容易理解

復(fù)雜點(diǎn)的

return !!(node.pre || (
		!node.hasBindings && // no dynamic bindings
		!node.if && !node.for && // not v-if or v-for or v-else
		!isBuiltInTag(node.tag) && // not a built-in
		isPlatformReservedTag(node.tag) && // not a component
		!isDirectChildOfTemplateFor(node) &&
		Object.keys(node).every(isStaticKey)
))

節(jié)點(diǎn)類型為表達(dá)式,標(biāo)注為非靜態(tài);普通文本為靜態(tài)。

  • 無動態(tài)綁定
  • 沒有 v-if 和 v-for 指令
  • 不是內(nèi)置的標(biāo)簽
  • 是平臺保留標(biāo)簽(html和svg標(biāo)簽)
  • 不是 template 標(biāo)簽的直接子元素并且沒有包含在 for 循環(huán)中
  • 結(jié)點(diǎn)包含的屬性只能有isStaticKey中指定的幾個(gè)

現(xiàn)在你知道了 node.static=isStatic(node) 什么情況為false, 什么情況為true吧!

回歸到markStatic$1

if (node.type === 1) {
	// do not make component slot content static. this avoids
	// 1. components not able to mutate slot nodes
	// 2. static slot content fails for hot-reloading
	if (
		!isPlatformReservedTag(node.tag) &&
		node.tag !== 'slot' &&
		node.attrsMap['inline-template'] == null
	) {
		return
	}
	for (var i = 0, l = node.children.length; i < l; i++) {
		var child = node.children[i];
		markStatic$1(child);
		if (!child.static) {
			node.static = false;
		}
	}
	if (node.ifConditions) {
		for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) {
			var block = node.ifConditions[i$1].block;
			markStatic$1(block);
			if (!block.static) {
				node.static = false;
			}
		}
	}
}

來看看它做了什么,通過一個(gè) if 判斷node.type值為1,對標(biāo)簽節(jié)點(diǎn)進(jìn)行處理。如果遇到特殊情況會直接退出去。 什么特殊情況呢?

// do not make component slot content static. this avoids
// 1. components not able to mutate slot nodes
// 2. static slot content fails for hot-reloading
if (
	!isPlatformReservedTag(node.tag) &&
	node.tag !== 'slot' &&
	node.attrsMap['inline-template'] == null
) {
	return
}

當(dāng)遇到了非平臺保留標(biāo)簽 isPlatformReservedTag(node.tag), 并且標(biāo)簽節(jié)點(diǎn)是 slot,并且節(jié)點(diǎn)中有inline-template(內(nèi)聯(lián)模板)三者都滿足此時(shí)會終止函數(shù)的執(zhí)行。

如果不滿足條件:

for (var i = 0, l = node.children.length; i &lt; l; i++) {
	var child = node.children[i];
	markStatic$1(child);
	if (!child.static) {
		node.static = false;
	}
}

通過 node.children 找到子節(jié)點(diǎn),遞歸子節(jié)點(diǎn)。

if (!child.static) {
     node.static = false;
}

子節(jié)點(diǎn)非靜態(tài),該節(jié)點(diǎn)也標(biāo)注非靜態(tài) 。這塊設(shè)計(jì)的不太合理有更多好的優(yōu)化方案,在Vue3.0中增加了"動靜分離的策略" 尤大稱之為 Block tree 后續(xù)在跟大家掰扯。

接下來看下 markStaticRoots。

markStaticRoots 源碼

function markStaticRoots(node, isInFor) {
	if (node.type === 1) {
		if (node.static || node.once) {
			node.staticInFor = isInFor;
		}
		//一個(gè)節(jié)點(diǎn)要成為根節(jié)點(diǎn),那么要滿足以下條件:
                //1、靜態(tài)節(jié)點(diǎn),并且有子節(jié)點(diǎn)
                //2、子節(jié)點(diǎn)不能僅為一個(gè)文本節(jié)點(diǎn)
		if (node.static &amp;&amp; node.children.length &amp;&amp; !(
				node.children.length === 1 &amp;&amp;
				node.children[0].type === 3
			)) {
			node.staticRoot = true;
			return
		} else {
			node.staticRoot = false;
		}
                //循環(huán)遞歸標(biāo)記
		if (node.children) {
			for (var i = 0, l = node.children.length; i &lt; l; i++) {
				markStaticRoots(node.children[i], isInFor || !!node.for);
			}
		}
		if (node.ifConditions) {
			for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 &lt; l$1; i$1++) {
				markStaticRoots(node.ifConditions[i$1].block, isInFor);
			}
		}
	}
}

一個(gè)節(jié)點(diǎn)要成為靜態(tài)根節(jié)點(diǎn),需要滿足以下條件:

  • 自身為靜態(tài)節(jié)點(diǎn),并且有子節(jié)點(diǎn)
  • 子節(jié)點(diǎn)不能僅為一個(gè)文本節(jié)點(diǎn)

對于第二個(gè)條件,主要考慮到標(biāo)記靜態(tài)根節(jié)點(diǎn)的受益較小。接下來遞歸循環(huán)其子節(jié)點(diǎn),循環(huán)標(biāo)記。

以上就是Vue 編譯器optimize源碼分析的詳細(xì)內(nèi)容,更多關(guān)于Vue 編譯器optimize的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue自定義js圖片碎片輪播圖切換效果的實(shí)現(xiàn)代碼

    vue自定義js圖片碎片輪播圖切換效果的實(shí)現(xiàn)代碼

    這篇文章主要介紹了vue自定義js圖片碎片輪播圖切換效果的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2019-04-04
  • 仿照Element-ui實(shí)現(xiàn)一個(gè)簡易的$message方法

    仿照Element-ui實(shí)現(xiàn)一個(gè)簡易的$message方法

    這篇文章主要介紹了仿照Element-ui實(shí)現(xiàn)一個(gè)簡易的$message方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • VUE引入騰訊地圖并實(shí)現(xiàn)軌跡動畫的詳細(xì)步驟

    VUE引入騰訊地圖并實(shí)現(xiàn)軌跡動畫的詳細(xì)步驟

    這篇文章主要介紹了VUE引入騰訊地圖并實(shí)現(xiàn)軌跡動畫,引入步驟大概是在 html 中通過引入 script 標(biāo)簽加載API服務(wù),結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • vue項(xiàng)目webpack中Npm傳遞參數(shù)配置不同域名接口

    vue項(xiàng)目webpack中Npm傳遞參數(shù)配置不同域名接口

    這篇文章主要介紹了vue項(xiàng)目webpack中Npm傳遞參數(shù)配置不同域名接口,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • vue中g(shù)et請求如何傳遞數(shù)組參數(shù)的方法示例

    vue中g(shù)et請求如何傳遞數(shù)組參數(shù)的方法示例

    這篇文章主要介紹了vue中g(shù)et請求如何傳遞數(shù)組參數(shù)的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • vue下載excel的實(shí)現(xiàn)代碼后臺用post方法

    vue下載excel的實(shí)現(xiàn)代碼后臺用post方法

    這篇文章主要介紹了vue下載excel的實(shí)現(xiàn)代碼,后臺用post方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-05-05
  • Vue生態(tài)的新成員Pinia的詳細(xì)介紹

    Vue生態(tài)的新成員Pinia的詳細(xì)介紹

    本文主要介紹了Vue生態(tài)的新成員Pinia的詳細(xì)介紹,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • vue中如何修改props傳進(jìn)來的值

    vue中如何修改props傳進(jìn)來的值

    大家應(yīng)該都知道vue是單向數(shù)據(jù)流,一般我們也不會在子組件里面修改父組件傳進(jìn)來的值,但總有需要修改的時(shí)候,這篇文章主要介紹了vue中修改props傳進(jìn)來的值,需要的朋友可以參考下
    2022-12-12
  • 關(guān)于vue單文件中引用路徑的處理方法

    關(guān)于vue單文件中引用路徑的處理方法

    這篇文章主要給大家介紹了關(guān)于vue單文件中引用路徑處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • vue基于better-scroll仿京東分類列表

    vue基于better-scroll仿京東分類列表

    這篇文章主要為大家詳細(xì)介紹了vue基于better-scroll仿京東分類列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06

最新評論

萨迦县| 孟村| 米脂县| 老河口市| 昭平县| 越西县| 雷山县| 古浪县| 潢川县| 孝感市| 德化县| 莱芜市| 松潘县| 日照市| 织金县| 长岛县| 肥乡县| 铜川市| 瑞昌市| 花莲县| 额尔古纳市| 丹寨县| 南通市| 乌苏市| 台南市| 江陵县| 报价| 婺源县| 乌鲁木齐市| 江山市| 镇远县| 斗六市| 富民县| 德令哈市| 贵定县| 乐都县| 库伦旗| 汕尾市| 清徐县| 宿迁市| 安吉县|