vue源碼解讀--parse(創(chuàng)建ast樹)

目錄導(dǎo)航

沿用上一節(jié)的示例代碼

定位斷點(diǎn)

上一節(jié)我們說到,在解析main過程中執(zhí)行handleStartTag的最后一步將會(huì)調(diào)用start函數(shù)生成ast節(jié)點(diǎn),將代碼定位于此,入?yún)椋簃ain、{attrs:{name:"id",value:"app",start:6,end:14}、false、0、15

handleStartTag

? ??\odot 調(diào)用createASTElement生成一個(gè)ast元素

(因此元素節(jié)點(diǎn)的ast節(jié)點(diǎn)為1)

? ??\odot process.env.NODE_ENV為開發(fā)環(huán)境進(jìn)入判斷,對(duì)attrs做一次遍歷,校驗(yàn)其合法性,比如不能包含引號(hào)、尖括號(hào)、等號(hào)等特殊字符

? ??\odot isForbiddenTag(element)當(dāng)前為false,對(duì)于符合其條件的代碼則是對(duì)一些特殊標(biāo)簽作校驗(yàn),如不能是style或script標(biāo)簽,因?yàn)檫@不會(huì)被解析

? ??\odot 調(diào)用preTransforms對(duì)v-model做特殊處理

? ??\odot 調(diào)用process開頭的函數(shù),process為加工,再結(jié)合for、if??梢酝茢喑鲈撎幨菍?duì)v-for等指令的處理。且處理過后,ast元素節(jié)點(diǎn)上會(huì)相應(yīng)的添加某些標(biāo)識(shí)

? ? ? ? 由于當(dāng)前的main標(biāo)簽不存在v-if或v-for指令,但是我們的示例中的ul存在v-if、li存在v-for。故我們分別跳到ul和li的位置。根據(jù)上一節(jié)的分析,我們知道此時(shí)的attrs的關(guān)鍵參數(shù)分別為{v-if:'isList'}、{v-for:'(v,i) in list'}

? ??????????\ominus processIf

? ??????????????????????\cong getAndRemoveAttr獲取v-if的值,即isList

? ??????????????????????\cong 進(jìn)入判斷向ast元素節(jié)點(diǎn)上添加if屬性,值為isList;并調(diào)用addIfCondition向節(jié)點(diǎn)添加ifConditions屬性,值為數(shù)組[{exp:isList,block:ast元素節(jié)點(diǎn)}]

? ? ? ? ? ? ??\ominus processFor

? ??????????????????????????\cong getAndRemoveAttr獲取v-for的值,即:(v,i) in list

? ??????????????????????????\cong parseFor解析出遍歷v、i、list

? ??????????????????????????\cong 調(diào)用extend向ast節(jié)點(diǎn)上添加for的標(biāo)識(shí)屬性:for:list,alias:v,iterator1:i

? ??\odot 回到start函數(shù),向下判斷當(dāng)前節(jié)點(diǎn)是否是單標(biāo)簽,如果不是,則currentParent=element,并向stack中push當(dāng)前的ast元素節(jié)點(diǎn)。那么這兩步操作究竟有何用呢?(我們當(dāng)前一直關(guān)注的都是開始標(biāo)簽的ast處理,故我們現(xiàn)在分析下結(jié)束標(biāo)簽的處理來看下是否能形成一個(gè)閉合)

parseEndTag

? ??\odot tagName="li",進(jìn)入判斷,根據(jù)之前分析,由于當(dāng)前在解析的流程中故stack中保存的是main、ul、li,將在pos=2時(shí)匹配到,進(jìn)入判斷,調(diào)用end函數(shù)

? ??????????????\oplus 拿到保存ast節(jié)點(diǎn)的stack,取到最后一位li。之后將stack中的最后一位pop掉,并且將currentParent指向上一位ul,后調(diào)用closeElement,將li(ast)元素傳入

? ??????????????????????????\bullet 框紅的位置,向父ast節(jié)點(diǎn)ul的children下保存了當(dāng)前的ast節(jié)點(diǎn)li,并讓當(dāng)前ast節(jié)點(diǎn)li的parent指向了父ast節(jié)點(diǎn)ul。


故,ast樹的創(chuàng)建過程實(shí)際上是針對(duì)不同的元素類型創(chuàng)建不同的ast節(jié)點(diǎn)類型,在每一次模板標(biāo)簽的解析過程中會(huì)將其屬性進(jìn)行解析并使用約定的標(biāo)識(shí)添加到ast節(jié)點(diǎn)上。并且ast節(jié)點(diǎn)之間通過children和parent來建立父子關(guān)系。最終建立起一個(gè)可以完美映射dom樹的節(jié)點(diǎn)樹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容