vue parseHTML函數(shù)源碼解析 AST預(yù)備知識(shí)
正文
接上章節(jié):parseHTML 函數(shù)源碼解析AST 基本形成
在正式扎進(jìn)Vue parse源碼之前,我們先了解下他周邊的工具函數(shù), 這能幫我們快速的去理解閱讀。
還記得我們?cè)谏险鹿?jié)講的element元素節(jié)點(diǎn)的描述對(duì)象嗎?
var element = { type: 1, tag: tag, parent: null, attrsList: attrs, children: [] }
在源碼中定義了一個(gè)createASTElement函數(shù),用來(lái)創(chuàng)建一個(gè)元素的描述對(duì)象。
createASTElement函數(shù)
function createASTElement(tag, attrs, parent) { return { type: 1, tag: tag, attrsList: attrs, attrsMap: makeAttrsMap(attrs), parent: parent, children: [] } }
解析指令所用正則
var onRE = /^@|^v-on:/; var dirRE = /^v-|^@|^:/; var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/; var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/; var stripParensRE = /^\(|\)$/g; var argRE = /:(.*)$/; var bindRE = /^:|^v-bind:/; var modifierRE = /\.[^.]+/g;
在解析開始標(biāo)簽的時(shí)候你遇到的不僅有屬性,還有一些Vue 自定義的指令。下面一起來(lái)分析下解析指令會(huì)有用哪些正則。
onRE
var onRE = /^@|^v-on:/;
匹配以字符 @ 或 v-on: 開頭的字符串,主要作用是檢測(cè)標(biāo)簽屬性名是否是監(jiān)聽事件的指令。
dirRE
var const dirRE = /^v-|^@|^:/
匹配以字符 v- 或 @ 或 : 開頭的字符串,主要作用是檢測(cè)標(biāo)簽屬性名是否是指令。在Vue中所有以 v- 開頭的屬性都被認(rèn)為是指令,另外@字符是 v-on 的縮寫,: 字符是 v-bind 的縮寫。
forAliasRE
var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
匹配 v-for 屬性的值,并捕獲 in 或 of 前后的字符串。都是正則大神就不解釋怎么捕獲的了。
forIteratorRE
var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
這個(gè)也是匹配v-for的屬性值,不過(guò)比之前要稍微復(fù)雜點(diǎn):列表渲染 v-for(https://cn.vuejs.org/v2/guide/list.html)需要先了解下這個(gè)。
//示例:1 <div v-for="(value, name) in object"> {{ name }}: {{ value }} </div> //示例:2 <div v-for="(value, name, index) in object"> {{ index }}. {{ name }}: {{ value }} </div>
沒(méi)錯(cuò)就是用來(lái)捕獲,示例1中的:'obj , index' 示例2中的:'value, key, index' 。
stripParensRE
var stripParensRE = /^\(|\)$/g;
這個(gè)捕獲組用來(lái)捕獲要么以字符 ( 開頭,要么以字符 ) 結(jié)尾的字符串,或者兩者都滿足。那么這個(gè)正則的作用是什么呢?我們?cè)谥v解正則 forIteratorRE 時(shí)有個(gè)細(xì)節(jié)不知道大家注意到了沒(méi)有,就是 forIteratorRE 正則所匹配的字符串是 'obj, index' ,而不是 '(obj, index)' ,這兩個(gè)字符串的區(qū)別就在于第二個(gè)字符串擁有左右括號(hào),所以在使用 forIteratorRE 正則之前,需要使用 stripParensRE 正則去掉字符串 '(obj, index)' 中的左右括號(hào),實(shí)現(xiàn)方式很簡(jiǎn)單:
"(obj, index)".replace(stripParensRE, "")
argRE
var argRE = /:(.*)$/;
argRE正則用來(lái)匹配指令編寫中的參數(shù),并且擁有一個(gè)捕獲組,用來(lái)捕獲參數(shù)的名字。
示例:
<div v-on:click.item="handle"></div>
其中 v-on 為指令,click為傳遞給 v-on 指令的參數(shù),stop 為修飾符。
bindRE
var bindRE = /^:|^v-bind:/;
該正則用來(lái)匹配以字符:
或字符串 v-bind: 開頭的字符串,主要用來(lái)檢測(cè)一個(gè)標(biāo)簽的屬性是否是綁定(v-bind)。
modifierRE
var modifierRE = /\.[^.]+/g;
該正則用來(lái)匹配修飾符的,但是并沒(méi)有捕獲任何東西,但你可以用match、exec等方法獲取與當(dāng)前正則匹配成功的信息。
parse 函數(shù)中的變量
在講解 parse 函數(shù)直接我們還需要先了解下它內(nèi)部所定義的一些變量以及用途。
function parse(template, options) { warn$2 = options.warn || baseWarn; platformIsPreTag = options.isPreTag || no; platformMustUseProp = options.mustUseProp || no; platformGetTagNamespace = options.getTagNamespace || no; transforms = pluckModuleFunction(options.modules, 'transformNode'); preTransforms = pluckModuleFunction(options.modules, 'preTransformNode'); postTransforms = pluckModuleFunction(options.modules, 'postTransformNode'); delimiters = options.delimiters; var stack = []; var preserveWhitespace = options.preserveWhitespace !== false; var root; var currentParent; var inVPre = false; var inPre = false; var warned = false; function warnOnce(msg) { //... } function closeElement(element) { //... } parseHTML(template, { warn: warn$2, expectHTML: options.expectHTML, isUnaryTag: options.isUnaryTag, canBeLeftOpenTag: options.canBeLeftOpenTag, shouldDecodeNewlines: options.shouldDecodeNewlines, shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref, shouldKeepComment: options.comments, start: function start(tag, attrs, unary) {}, end: function end() {}, chars: function chars(text) {}, comment: function comment(text) {}, }); return root }
我們先來(lái)看下針對(duì)web平臺(tái)初始化的一些變量。
warn$2 = options.warn || baseWarn; platformIsPreTag = options.isPreTag || no; platformMustUseProp = options.mustUseProp || no; platformGetTagNamespace = options.getTagNamespace || no; transforms = pluckModuleFunction(options.modules, 'transformNode'); preTransforms = pluckModuleFunction(options.modules, 'preTransformNode'); postTransforms = pluckModuleFunction(options.modules, 'postTransformNode'); delimiters = options.delimiters;
- warn$2 函數(shù) 毋庸置疑它作用是用來(lái)打印警告信息的
- platformIsPreTag 函數(shù)是一個(gè)編譯器選項(xiàng),其作用是通過(guò)給定的標(biāo)簽名字判斷該標(biāo)簽是否是 pre 標(biāo)簽。
- platformMustUseProp 該函數(shù)也是一個(gè)編譯器選項(xiàng),其作用是用來(lái)檢測(cè)一個(gè)屬性在標(biāo)簽中是否要使用元素對(duì)象原生的 prop 進(jìn)行綁定。
- platformGetTagNamespace 該函數(shù)是一個(gè)編譯器選項(xiàng),其作用是用來(lái)獲取元素(標(biāo)簽)的命名空間。
- transforms 、preTransforms 、postTransforms 還沒(méi)講到它們的上下文,暫時(shí)不解釋它們的作用。
- delimiters 它的值為 options.delimiters 屬性,它的值就是在創(chuàng)建 Vue 實(shí)例對(duì)象時(shí)所傳遞的 delimiters 選項(xiàng)。
繼續(xù)往下看:
var stack = []; var preserveWhitespace = options.preserveWhitespace !== false; var root; var currentParent; var inVPre = false; var inPre = false; var warned = false;
- stack 初始值是一個(gè)空數(shù)組,作用在上個(gè)章節(jié)我們講到,回退操作為了讓子元素描述對(duì)象的parent屬性能夠正確指向其父元素。
- preserveWhitespace 是一個(gè)布爾值并且它的值與編譯器選項(xiàng)中的options.preserveWhitespace選項(xiàng)有關(guān),只要 options.preserveWhitespace 的值不為false,那么 preserveWhitespace 的值就為真。其中 options.preserveWhitespace 選項(xiàng)用來(lái)告訴編譯器在編譯 html 字符串時(shí)是否放棄標(biāo)簽之間的空格,如果為 true 則代表放棄。
- root 存儲(chǔ)最終生成的AST。
- currentParent 通過(guò)上章節(jié)了解到,該變量維護(hù)元素描述對(duì)象之間的父子關(guān)系。
- inVPre 初始值:false。標(biāo)識(shí)當(dāng)前解析的標(biāo)簽是否在擁有 v-pre (跳過(guò)這個(gè)元素和它的子元素的編譯過(guò)程。)的標(biāo)簽之內(nèi)。
- inPre 初始值:false。標(biāo)識(shí)當(dāng)前正在解析的標(biāo)簽是否在 <pre></pre> 標(biāo)簽之內(nèi)。
- warned 初始值:false。用來(lái)打印警告信息的函數(shù),只不過(guò) warnOnce 函數(shù)就如它的名字一樣,只會(huì)打印一次警告信息,并且 warnOnce 函數(shù)也是通過(guò)調(diào)用 warn 函數(shù)來(lái)實(shí)現(xiàn)的。
好了一些邊邊角角的東西就先講到這,接下來(lái)我們一起來(lái)分析Vue parse源碼看看一顆完整的AST樹是如何構(gòu)建出來(lái)的。更多關(guān)于vue parseHTML函數(shù)AST預(yù)備的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+axios全局添加請(qǐng)求頭和參數(shù)操作
這篇文章主要介紹了vue+axios全局添加請(qǐng)求頭和參數(shù)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07vue實(shí)現(xiàn)頁(yè)面上傳文件夾壓縮后傳給服務(wù)器的操作
這篇文章主要介紹了vue實(shí)現(xiàn)頁(yè)面上傳文件夾壓縮后傳給服務(wù)器的操作,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09Vue-drag-resize 拖拽縮放插件的使用(簡(jiǎn)單示例)
本文通過(guò)代碼給大家介紹了Vue-drag-resize 拖拽縮放插件使用簡(jiǎn)單示例,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Vue3項(xiàng)目中引入ElementUI并使用的示例詳解
ElementUI是一個(gè)強(qiáng)大的PC端UI組件框架,它不依賴于vue,但是卻是當(dāng)前和vue配合做項(xiàng)目開發(fā)的一個(gè)比較好的ui框架,本文主要介紹了如何在vue3中引入使用ElementUI,需要的可以參考一下2023-06-06VUE數(shù)組根據(jù)索引刪除數(shù)據(jù),頁(yè)面同時(shí)更新的實(shí)現(xiàn)方法
這篇文章主要介紹了VUE數(shù)組根據(jù)索引刪除數(shù)據(jù),頁(yè)面同時(shí)更新的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07vue插件draggable實(shí)現(xiàn)拖拽移動(dòng)圖片順序
這篇文章主要為大家詳細(xì)介紹了vue插件draggable實(shí)現(xiàn)拖拽移動(dòng)圖片順序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12vue實(shí)現(xiàn)頁(yè)面加載動(dòng)畫效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)頁(yè)面加載動(dòng)畫效果,vue頁(yè)面出現(xiàn)正在加載的初始頁(yè)面與實(shí)現(xiàn)動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09vue+elementUI實(shí)現(xiàn)表單和圖片上傳及驗(yàn)證功能示例
這篇文章主要介紹了vue+elementUI實(shí)現(xiàn)表單和圖片上傳及驗(yàn)證功能,結(jié)合實(shí)例形式分析了vue+elementUI表單相關(guān)操作技巧,需要的朋友可以參考下2019-05-05