Vue 2源碼解析HTMLParserOptions.start函數(shù)方法
HTMLParserOptions.start()
用來解析標簽的開始部分(匹配到標簽開始部分時調用),主要區(qū)分標簽類型、解析標簽指令配置與動態(tài)綁定參數(shù)等等。
let root let currentParent function start(tag, attrs, unary, start, end) { const ns = (currentParent && currentParent.ns) || platformGetTagNamespace(tag) if (isIE && ns === 'svg') attrs = guardIESVGBug(attrs) let element: ASTElement = createASTElement(tag, attrs, currentParent) if (ns) element.ns = ns if (__DEV__) { if (options.outputSourceRange) { element.start = start element.end = end element.rawAttrsMap = element.attrsList.reduce((cumulated, attr) ={ cumulated[attr.name] = attr return cumulated }, {}) } attrs.forEach(attr =invalidAttributeRE.test(attr.name) && warn('')) } if (isForbiddenTag(element) && !isServerRendering()) { element.forbidden = true __DEV__ && warn('') } for (let i = 0; i < preTransforms.length; i++) { element = preTransforms[i](element, options) || element } if (!inVPre) { processPre(element) if (element.pre) inVPre = true } if (platformIsPreTag(element.tag)) inPre = true if (inVPre) processRawAttrs(element) else if (!element.processed) { processFor(element) processIf(element) processOnce(element) } if (!root) { root = element if (__DEV__) checkRootConstraints(root) } if (!unary) { currentParent = element stack.push(element) } else { closeElement(element) } },
start 函數(shù)在解析完標簽的開始部分后被調用,接收的五個參數(shù)分別是:標簽名 tag,標簽的屬性數(shù)組 attrs,是否自閉合 unary,起點位置 start,結束位置 end
- 進入函數(shù)之后,首先會驗證 當前元素的父元素的標簽命名空間(svg,math或者undefined),如果是 svg 元素,還會對解析出來的 attrs 對象進行處理,去掉 svg 標簽定義屬性(xmlns 之類的屬性)
- 調用 createASTElement(tag, attrs, currentParent) 方法創(chuàng)建當前元素對應的 AST 對象 element。此時結構如下:
{ type: 1, tag: tag, attrsList: attrs, attrsMap: makeAttrsMap(attrs), rawAttrsMap: {}, parent: currentParent, children: [] }
- 在開發(fā)環(huán)境下,還會將節(jié)點在字符串中的位置與節(jié)點原有的屬性進行記錄,并且 校驗屬性名 是否合法(禁止空格,引號,尖括號,反斜杠和等號)
- 校驗標簽合法性,如果是 style,script 之類的標簽會被標記為“被禁止”(element.forbidden = true)
- 遍歷 preTransforms 數(shù)組配置的處理函數(shù),分別處理當前節(jié)點的 ast 結果,并重新更新節(jié)點的 ast 對象(這里只處理 input)
處理后的 input ast element
這里處理后的 input ast element,會比基礎的 ast element 要多一些屬性:
{ attrs: [], attrsList: [], attrsMap: { 'v-model': 'xxx' }, chidlren: [], derectives: [{ isDynamicArg: false, modifiers: undefined, name: 'model', rawName: 'model', value: 'xxx' }], events: { input: { dynamic: undefined, value: "if($event.target.composing)return;xxx=$event.target.value" } }, hasBindings: true, parent: currentParent, plain: false, props: [{ dynamic: undefined, name: 'value', value: '(xxx)' }], rawAttrsMap: {}, static: false }
雖然上面也省略了幾個屬性和部分屬性值,但是重點屬性都在里面。在 preTransforms 過程中,實際上是通過 preTransformNode() 函數(shù)處理 input 標簽,并且該標簽具有 v-model 配置,沒有 v-model 時直接退出。
之后會判斷該元素是否有動態(tài)綁定類型,如果是 動態(tài)綁定的元素類型,則會增加一個 ifConditions 配置,內部會填充 checkbox, radio 和 其他 input 類型的標簽,用來根據(jù)不同的情況顯示不同的展示形式(個人理解這里為什么只有三種,是因為 checkbox 和 radio 與其他的 input 輸入框差別比較大,而且需要 label 標簽配合)
- 判斷元素有沒有設置 v-pre 指令或者是一個 pre 標簽,重新設置 inVPre, inPre 的狀態(tài)
- 如果此時 inVPre === true,則直接跳過這個節(jié)點內部的編譯;否則會依次判斷 v-for,v-if 和 v-once 配置并進行編譯
這里會先判斷 for 循環(huán)再判斷 if 條件,所以才有 for 的優(yōu)先級高于 if。
如果存在 v-for,會在 ast 對象中添加 for 和 forProcessed 屬性,并解析條件;如果內部有文本節(jié)點要顯示循環(huán)的值,則會在標簽最末級創(chuàng)建一個文本節(jié)點并綁定顯示條件
如果存在 v-if,會在 ast 對象中添加 if 和 ifProcessed 屬性,并添加一個 ifConditions 屬性,存放不同條件下的 ast 節(jié)點對象和渲染條件
如果有 v-once,一樣會在 ast 對象中添加 once 和 onceProcessed,并且會標記 staticProcessed
- 上面的過程執(zhí)行完之后,如果此時外部的 root 是 undefined,則會將當前的節(jié)點作為根元素賦值給 root,并調用 checkRootConstraints 檢查根節(jié)點
- 如果當前節(jié)點是一個自閉合標簽,則直接調用 closeElement 結束該節(jié)點;不然則將該節(jié)點賦值給 currentParent 并插入 stack 解析棧,以供子節(jié)點的解析
以上就是Vue 2源碼解析HTMLParserOptions.start函數(shù)方法的詳細內容,更多關于Vue HTMLParserOptions.start的資料請關注腳本之家其它相關文章!
相關文章
vue中el-checkbox、el-switch綁定值問題詳解
這篇文章主要給大家介紹了關于vue中el-checkbox、el-switch綁定值問題的相關資料,文中通過代碼介紹的非常詳細,對大家學習或者使用vue具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01詳解vue-cli項目中用json-sever搭建mock服務器
這篇文章主要介紹了詳解vue-cli項目中用json-sever搭建mock服務器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11