Vue?2源碼解析ParseHTML函數(shù)HTML模板
ParseHTML函數(shù) - HTML 模板解析
之前在解析 parse 函數(shù)時,我們知道整個 解析 template 模板并生成 ast 對象 的過程都發(fā)生在這個函數(shù)的執(zhí)行過程中。
但是 parse 函數(shù)內(nèi)部本身只定義了一些標(biāo)簽、指令的處理方法和警告函數(shù),并且在傳遞給 parseHTML 函數(shù)的參數(shù)中定義了四個處理方法。
最終是通過調(diào)用 parseHTML 來解析 template 模板
整個解析過程,其實就是 通過一系列正則表達式來匹配 template 模板字符串,并截取該部分匹配內(nèi)容并重新匹配剩余部分,直到全部匹配完成。
所有的正則表達式包含以下內(nèi)容:
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ // 靜態(tài)屬性解析 const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ // 動態(tài)屬性解析(含有 v-xxx:, :, @, # 的屬性) const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*` const qnameCapture = `((?:${ncname}\\:)?${ncname})` const startTagOpen = new RegExp(`^<${qnameCapture}`) // 開始標(biāo)簽部分 const startTagClose = /^\s*(\/?)>/ // 開始標(biāo)簽結(jié)束 const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)// 結(jié)束標(biāo)簽部分 const doctype = /^<!DOCTYPE [^>]+>/i // DOCTYPE 聲明 const comment = /^<!\--/ // 注釋部分 const conditionalComment = /^<!\[/ // 條件注釋
而 parseHTML 的簡要代碼如下:
export function parseHTML(html, options: HTMLParserOptions) { const stack: any[] = [] const expectHTML = options.expectHTML const isUnaryTag = options.isUnaryTag || no const canBeLeftOpenTag = options.canBeLeftOpenTag || no let index = 0 let last, lastTag while (html) { last = html if (!lastTag || !isPlainTextElement(lastTag)) { let textEnd = html.indexOf('<') if (textEnd === 0) { if (comment.test(html)) { // 處理 注釋 advance() continue } if (conditionalComment.test(html)) { // 處理 條件注釋 advance() continue } // Doctype: if (html.match(doctype)) { advance() continue } // 結(jié)束: if (html.match(endTag)) { advance() parseEndTag() continue } // 開始: if (parseStartTag()) { advance() handleStartTag() continue } } // 處理純文本 options.chars() advance() } else { // 結(jié)束 parseEndTag() } if (html === last) { options.chars && options.chars(html) break } } parseEndTag() function advance(n) { } function parseStartTag() { } function handleStartTag(match) { } function parseEndTag(tagName?: any, start?: any, end?: any) { } }
其中定義了三個標(biāo)簽處理方法和一個定位方法:
- advance 方法是更新當(dāng)前解析到的文本位置 index,并截取掉已解析的部分
- parseStartTag 方法用來解析標(biāo)簽的開始部分,內(nèi)部會生成一個包含標(biāo)簽名 tagName 和屬性數(shù)組 attrs 的對象 math,并循環(huán)解析內(nèi)部的字符串直到解析完整個字符串,將解析到的屬性存放到 attrs 數(shù)組中
- handleStartTag 則是處理 parseStartTag 得到的 math 對象(大部分是處理每個屬性),如果上面解析到是非閉合標(biāo)簽的話,也會將這個 math 對象修改成一個新對象插入到 parseHTML 執(zhí)行時定義的 stack 元素棧中;當(dāng)然,如果是自閉合標(biāo)簽,還會調(diào)用 parseEndTag 方法處理;并在 最后調(diào)用 options 中定義的 start 函數(shù)來生成 ast 對象
- parseEndTag 方法就用來處理標(biāo)簽結(jié)束后的邏輯,會根據(jù)條件清除 stack 棧中的元素;如果此時元素標(biāo)簽是 br 或者 p,也會調(diào)用 option.start(),其他情況下一般會調(diào)用 options.end() 來結(jié)束當(dāng)前標(biāo)簽的解析
總的來說,parseHTML 就是通過正則表達式來匹配不同的標(biāo)簽和屬性,進行不同的標(biāo)簽/屬性處理,最后通過 options 中的回調(diào)函數(shù)來創(chuàng)建完整的 ast 對象;并用 stack 元素棧的方式來保證原始 template 模板與 ast 對象的層級結(jié)構(gòu)的一致性。
以上就是Vue 2源碼解析ParseHTML函數(shù)HTML模板的詳細內(nèi)容,更多關(guān)于Vue ParseHTML函數(shù)模板的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue中 el-table每個單元格包含多個數(shù)據(jù)項處理
vue項目中,我們需要在el-table中顯示數(shù)組數(shù)據(jù),有的時候,需要在一個單元格中顯示多條數(shù)據(jù),如何實現(xiàn)呢,對vue el-table單元格相關(guān)知識感興趣的朋友一起看看吧2023-11-11Element?Plus組件Form表單Table表格二次封裝的完整過程
一般在后臺管理系統(tǒng)的開發(fā)中,都會遇到很多table,但每一次都去引入el-table就會導(dǎo)致代碼十分冗余,所以基于組件做一下二次封裝成自己需要的組件就十分nice,下面這篇文章主要給大家介紹了關(guān)于Element?Plus組件Form表單Table表格二次封裝的相關(guān)資料,需要的朋友可以參考下2022-09-09