vue?parseHTML?函數(shù)拿到返回值后的處理源碼解析
引言
繼上篇文章:
var startTagMatch = parseStartTag();
if (startTagMatch) {
handleStartTag(startTagMatch);
if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) {
advance(1);
}
continue
}
在上個章節(jié)中知道startTagMatch 就是獲取parseStartTag函數(shù)的返回值。并只有在成功匹配到開始標簽的情況下parseStartTag 才會返回解析結(jié)果(一個對象),否則返回undefined。
假設(shè)有如下html(template)字符串:
<div id="box" v-if="watings"></div>
parseStartTag函數(shù)返回值
則parseStartTag函數(shù)的返回值如下:
match = {
tagName: 'div',
attrs: [
[
'id="box"',
'id',
'=',
'box',
undefined,
undefined
],
[
' v-if="watings"',
'v-if',
'=',
'watings',
undefined,
undefined
]
],
start: index,
unarySlash: undefined,
end: index
}
handleStartTag源碼
現(xiàn)在我們假設(shè)匹配成功,那么if語句塊中的代碼將會被執(zhí)行,此時會將解析結(jié)果作為參數(shù)傳遞給 handleStartTag 函數(shù),handleStartTag源碼如下:
function handleStartTag(match) {
var tagName = match.tagName;
var unarySlash = match.unarySlash;
if (expectHTML) {
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
parseEndTag(lastTag);
}
if (canBeLeftOpenTag$$1(tagName) && lastTag === tagName) {
parseEndTag(tagName);
}
}
var unary = isUnaryTag$$1(tagName) || !!unarySlash;
var l = match.attrs.length;
var attrs = new Array(l);
for (var i = 0; i < l; i++) {
var args = match.attrs[i];
var value = args[3] || args[4] || args[5] || '';
var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' ?
options.shouldDecodeNewlinesForHref :
options.shouldDecodeNewlines;
attrs[i] = {
name: args[1],
value: decodeAttr(value, shouldDecodeNewlines)
};
}
if (!unary) {
stack.push({
tag: tagName,
lowerCasedTag: tagName.toLowerCase(),
attrs: attrs
});
lastTag = tagName;
}
if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end);
}
}
tagName 及unarySlash
handleStartTag函數(shù)用來處理開始標簽的解析結(jié)果,所以它接收parseStartTag函數(shù)的返回值作為參數(shù)。handleStartTag函數(shù)的一開始定義兩個常量:tagName 以及 unarySlash:
var tagName = match.tagName; var unarySlash = match.unarySlash;
根據(jù)上章節(jié)的內(nèi)容就能理解,tagName 存儲解析開始標簽的標簽名,unarySlash 可以根據(jù)他的值判斷是解析的開始標簽是否為一元標簽。
接著是一個if語句塊,if語句的判斷條件是if (expectHTML),前面說過expectHTML 是parser選項,是一個布爾值,如果為真則該 if 語句塊的代碼將被執(zhí)行。但是現(xiàn)在我們暫時不看這段代碼,因為這段代碼包含 parseEndTag 函數(shù)的調(diào)用,所以待我們講解完 parseEndTag 函數(shù)之后,再回頭來說這段代碼。
在往下定義了三個變量:
var unary = isUnaryTag$$1(tagName) || !!unarySlash; var l = match.attrs.length; var attrs = new Array(l);
變量 unary 是一個布爾值,當(dāng)它為真時代表著標簽是一元標簽,否則是二元標簽。
他們通過isUnaryTag來判斷,其原理通過傳遞的標簽名判斷是否有跟預(yù)設(shè)標準HTML中規(guī)定的那些一元標簽一致。
l 和 attrs ,其中常量 l 的值存儲著 match.attrs 數(shù)組的長度,而 attrs 常量則是一個與match.attrs數(shù)組長度相等的數(shù)組。
這兩個常量將被用于接下來的for循環(huán)中:
for (var i = 0; i < l; i++) {
var args = match.attrs[i];
var value = args[3] || args[4] || args[5] || '';
var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' ?
options.shouldDecodeNewlinesForHref :
options.shouldDecodeNewlines;
attrs[i] = {
name: args[1],
value: decodeAttr(value, shouldDecodeNewlines)
};
}
具體看一下循環(huán)體的代碼,首先定義 args 常量,它的值就是每個屬性的解析結(jié)果,即match.attrs 數(shù)組中的元素對象。
變量 value 中就保存著最終的屬性值,如果第4、5、6 項都沒有獲取到屬性值,那么屬性值將被設(shè)置為一個空字符串:''。
屬性值獲取到了之后,就可以拼裝最終的 attrs 數(shù)組。
attrs 數(shù)組的每個元素對象只包含兩個元素,即屬性名 name 和屬性值 value ,對于屬性名直接從 args[1] 中即可獲取,但我們發(fā)現(xiàn)屬性值卻沒有直接使用前面獲取到的 value ,而是將傳value 遞給了decodeAttr 函數(shù),并使用該函數(shù)的返回值作為最終的屬性值。
decodeAttr 函數(shù)的作用是對屬性值中所包含的 html 實體進行解碼,將其轉(zhuǎn)換為實體對應(yīng)的字符。關(guān)于 shouldDecodeNewlinesForHref 與 shouldDecodeNewlines 可回顧章節(jié)
Vue編譯器源碼分析compileToFunctions作用
接下來是:
if (!unary) {
stack.push({
tag: tagName,
lowerCasedTag: tagName.toLowerCase(),
attrs: attrs
});
lastTag = tagName;
}
這個if條件是當(dāng)開始標簽是非一元標簽時才會執(zhí)行,其目的是: 如果開始標簽是非一元標簽,則將該開始標簽的信息入棧,即push到stack數(shù)組中,并將lastTag的值設(shè)置為該標簽名。
在講解 parseHTML 函數(shù)開頭定義的變量和常量的過程中,我們講解過 stack 常量以及l(fā)astTage 變量,其目的是將來判斷是否缺少閉合標簽,并且現(xiàn)在大家應(yīng)該知道為什么 lastTag 所存儲的標簽名字始終保存著 stack 棧頂?shù)脑亓恕?/p>
調(diào)用parser鉤子函數(shù)
最后一段代碼調(diào)用parser鉤子函數(shù)的:
if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end);
}
如果 parser 選項中包含 options.start 函數(shù),則調(diào)用之,并將開始標簽的名字 tagName ,格式化后的屬性數(shù)組 attrs ,是否為一元標簽 unary ,以及開始標簽在原 html 中的開始和結(jié)束位置match.start 和 match.end 作為參數(shù)傳遞。
接下來我們分析 parse 到結(jié)束標簽之后會怎么做。
parseHTML 函數(shù)源碼解析之解析器遇到結(jié)束標簽
以上就是vue parseHTML 函數(shù)源碼解析的詳細內(nèi)容,更多關(guān)于vue parseHTML 函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
unplugin-svg-component優(yōu)雅使用svg圖標指南
這篇文章主要為大家介紹了unplugin-svg-component優(yōu)雅使用svg圖標指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
vue按住shift鍵多選方式(以element框架的table為例)
這篇文章主要介紹了vue按住shift鍵多選方式(以element框架的table為例),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
vue+elementUI動態(tài)生成面包屑導(dǎo)航教程
今天小編就為大家分享一篇vue+elementUI動態(tài)生成面包屑導(dǎo)航教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11

