在說Vue parse源碼之前,首先要了解周邊的工具函數。
之前見過element元素節點四描述對象?
var element = { type: 1, tag: tag, parent: null, attrsList: attrs, children: [] }
是用一個createASTElement函數,創建函數對象。
createASTElement函數
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;
現在我們一起來說下指令解析,還有關于一些Vue 自定義的指令
onRE
var onRE = /^@|^v-on:/;
匹配以字符 @ 或 v-on: 開頭的字符串,主要作用是檢測標簽屬性名是否是監聽事件的指令。
dirRE var const dirRE = /^v-|^@|^:/
匹配以字符 v- 或 @ 或 : 開頭的字符串,主要作用是檢測標簽屬性名是否是指令。在Vue中所有以 v- 開頭的屬性都被認為是指令,另外@字符是 v-on 的縮寫,: 字符是 v-bind 的縮寫。
forAliasRE
var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
匹配 v-for 屬性的值,并捕獲 in 或 of 前后的字符串。都是正則大神就不解釋怎么捕獲的了。
forIteratorRE
var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
這個也是匹配v-for的屬性值,不過比之前要稍微復雜點:列表渲染 v-for(https://cn.vuejs.org/v2/guide/list.html)需要先了解下這個。
//示例:1 <div v-for="(value, name) in object"> {{ name }}: {{ value }} </div> //示例:2 <div v-for="(value, name, index) in object"> {{ index }}. {{ name }}: {{ value }} </div>
沒錯就是用來捕獲,示例1中的:'obj , index' 示例2中的:'value, key, index' 。
stripParensRE
var stripParensRE = /^\(|\)$/g;
上面代碼是用來捕獲組用來,要么以字符 ( 開頭,要么以字符 ) 結尾的字符串,或者兩者都滿足。那正則的作用是什么呢?現在說的正則 forIteratorRE 時重要細節就是 forIteratorRE 正則所匹配的字符串是 'obj, index' ,而不是 '(obj, index)' ,這兩個字符串的區別就在于第二個字符串擁有左右括號,所以在使用 forIteratorRE 正則之前,需要使用 stripParensRE 正則去掉字符串 '(obj, index)' 中的左右括號,實現方式很簡單:
"(obj, index)".replace(stripParensRE, "")
argRE
var argRE = /:(.*)$/;
argRE正則用來匹配指令編寫中的參數,并且擁有一個捕獲組,用來捕獲參數的名字。
示例:
<div v-on:click.item="handle"></div>
其中 v-on 為指令,click為傳遞給 v-on 指令的參數,stop 為修飾符。
bindRE
var bindRE = /^:|^v-bind:/;
該正則用來匹配以字符:或字符串 v-bind: 開頭的字符串,主要用來檢測一個標簽的屬性是否是綁定(v-bind)。
modifierRE
var modifierRE = /\.[^.]+/g;
該正則用來匹配修飾符的,但是并沒有捕獲任何東西,但你可以用match、exec等方法獲取與當前正則匹配成功的信息。
parse 函數中的變量
講解 parse 函數前要先說內部所定義一些變量以及用途。
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 }
我們先來看下針對web平臺初始化的一些變量。
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 函數是用來打印警告信息;
platformIsPreTag 函數是一個編譯器選項,其作用是通過給定的標簽名字判斷該標簽是否是 pre 標簽。
platformMustUseProp 該函數也是一個編譯器選項,用來檢測一個屬性在標簽中是否要使用元素對象原生的 prop 進行綁定。
platformGetTagNamespace 該函數是一個編譯器選項,其作用是用來獲取元素(標簽)的命名空間。
transforms 、preTransforms 、postTransforms 還沒講到它們的上下文,暫時不解釋它們的作用。
delimiters 它的值為 options.delimiters 屬性,它的值就是在創建 Vue 實例對象時所傳遞的 delimiters 選項。
繼續往下看:
var stack = []; var preserveWhitespace = options.preserveWhitespace !== false; var root; var currentParent; var inVPre = false; var inPre = false; var warned = false;
stack的初始值是空,主要是回退操作為了讓子元素描述對象的parent屬性能夠正確指向其父元素。
preserveWhitespace 是一個布爾值,且與編譯器選項中的options.preserveWhitespace選項有關。當 options.preserveWhitespace 的值不為false,preserveWhitespace 的值就為真。但options.preserveWhitespace 選項用來告訴編譯器在編譯 html 字符串時是否放棄標簽之間的空格,如果為 true 則代表放棄。
root 存儲最終生成的AST。currentParent 變量維護元素描述對象之間的父子關系。
inVPre 初始值:false。標識當前解析的標簽是否在擁有 v-pre (跳過這個元素和它的子元素的編譯過程。)的標簽之內。
inPre 初始值:false。表示解析的標簽是否在 <pre></pre> 標簽之內。
warned 初始值:false。用來打印警告信息的函數,只不過 warnOnce 函數就如它的名字一樣,只會打印一次警告信息,并且 warnOnce 函數也是通過調用 warn 函數來實現的。
好吧!就講到現在,后面更多關于vue parseHTML函數源碼解析AST更多內容。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/127762.html
寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Compile - 源碼版 之 Parse 主要流程 本文難度較繁瑣,需要耐心觀看,如果你對 compile 源碼暫時...
摘要:下面用具體代碼進行分析。匹配不到那么就是開始標簽,調用函數解析。如這里的轉化為加上是為了的下一步轉為函數,本文中暫時不會用到。再把轉化后的內容進。 什么是AST 在Vue的mount過程中,template會被編譯成AST語法樹,AST是指抽象語法樹(abstract syntax tree或者縮寫為AST),或者語法樹(syntax tree),是源代碼的抽象語法結構的樹狀表現形式。...
vue parseHTML函數解析器遇到結束標簽,在之前文章中已講述完畢。 例如有html(template)字符串: <divid="app"> <p>{{message}}</p> </div> 產出如下: { attrs:["id="app"","id...
摘要:模板解析器原理本文來自深入淺出模板編譯原理篇的第九章,主要講述了如何將模板解析成,這一章的內容是全書最復雜且燒腦的章節。循環模板的偽代碼如下截取模板字符串并觸發鉤子函數為了方便理解,我們手動模擬解析器的解析過程。 Vue.js 模板解析器原理 本文來自《深入淺出Vue.js》模板編譯原理篇的第九章,主要講述了如何將模板解析成AST,這一章的內容是全書最復雜且燒腦的章節。本文未經排版,真...
直接進入核心現在說說baseCompile核心代碼: //`createCompilerCreator`allowscreatingcompilersthatusealternative //parser/optimizer/codegen,e.gtheSSRoptimizingcompiler. //Herewejustexportadefaultcompilerusingthede...
閱讀 547·2023-03-27 18:33
閱讀 732·2023-03-26 17:27
閱讀 630·2023-03-26 17:14
閱讀 591·2023-03-17 21:13
閱讀 521·2023-03-17 08:28
閱讀 1801·2023-02-27 22:32
閱讀 1292·2023-02-27 22:27
閱讀 2178·2023-01-20 08:28