摘要:源碼解析這邊解析的是從樹(shù)轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個(gè)語(yǔ)法樹(shù)轉(zhuǎn)函數(shù)的起點(diǎn)是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語(yǔ)法樹(shù),內(nèi)部調(diào)用函數(shù)開(kāi)始解析根節(jié)點(diǎn)容器節(jié)點(diǎn)。
開(kāi)始通過(guò)對(duì) Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫:
模版字符串轉(zhuǎn)AST語(yǔ)法樹(shù)
AST語(yǔ)法樹(shù)轉(zhuǎn)render函數(shù)
Vue雙向綁定原理
Vue虛擬dom比較原理
其中包含自己的理解和源碼的分析,盡量通俗易懂!由于是2.0的最早提交,所以和最新版本有很多差異、bug,后續(xù)將陸續(xù)補(bǔ)充,敬請(qǐng)諒解!包含中文注釋的Vue源碼已上傳...
今天要說(shuō)的代碼全在codegen文件夾中,在說(shuō)實(shí)現(xiàn)原理前,還是先看個(gè)簡(jiǎn)單的例子!
{{msg}}
上述類名為container的元素節(jié)點(diǎn)包含5個(gè)子節(jié)點(diǎn)(其中3個(gè)是換行文本節(jié)點(diǎn)),轉(zhuǎn)化成的AST語(yǔ)法樹(shù):
AST語(yǔ)法樹(shù)轉(zhuǎn)的render函數(shù)長(zhǎng)這樣:
function _render() { with (this) { return __h__( "div", {staticClass: "container"}, [ " ", __h__("span", {}, [String((msg))]), " ", __h__("button", {class: {active: isActive},on:{"click":handle}}, ["change msg"]), " " ] ) }; }
可以的看出,render函數(shù)做的事情很簡(jiǎn)單,就是把語(yǔ)法樹(shù)每個(gè)節(jié)點(diǎn)的指令進(jìn)行解析。
看下render函數(shù),它是由with函數(shù)包裹(為了改變作用域),要用的時(shí)候直接_render.call(vm);另外就是__h__函數(shù),這個(gè)后面會(huì)說(shuō)到,這個(gè)函數(shù)用于元素節(jié)點(diǎn)的解析,接收3個(gè)參數(shù):元素節(jié)點(diǎn)標(biāo)簽名,節(jié)點(diǎn)數(shù)據(jù),子節(jié)點(diǎn)數(shù)據(jù)。這個(gè)函數(shù)最后返回的就是虛擬dom了,不過(guò)今天先不深究,先說(shuō)如何生成這樣的render函數(shù),主要是v-if、v-for、v-bind、v-on等指令的解析。
源碼解析這邊解析的是從AST樹(shù)轉(zhuǎn)換成render函數(shù)部分的源碼,由于vue2.0第一次提交的源碼這部分不全,故做了部分更新,代碼全在codegen文件夾中。
入口整個(gè)AST語(yǔ)法樹(shù)轉(zhuǎn)render函數(shù)的起點(diǎn)是index.js文件中的generate()函數(shù):
export function generate (ast) { const code = genElement(ast); return new Function (`with (this) { return ${code}}`); }
明顯看到,generate()函數(shù)傳入?yún)?shù)為AST語(yǔ)法樹(shù),內(nèi)部調(diào)用genElement()函數(shù)開(kāi)始解析根節(jié)點(diǎn)(容器節(jié)點(diǎn))。genElement()函數(shù)用于解析元素節(jié)點(diǎn),它接收兩個(gè)參數(shù):AST對(duì)象和節(jié)點(diǎn)標(biāo)識(shí)(v-for的key),最后返回形如__h__("div", {}, [])的字符串,看一下內(nèi)部邏輯:
function genElement (el, key) { let exp; if (exp = getAndRemoveAttr(el, "v-for")) { // 解析v-for指令 return genFor(el, exp); } else if (exp = getAndRemoveAttr(el, "v-if")) { // 解析v-if指令 return genIf(el, exp, key); } else if (el.tag === "template") { // 解析子組件 return genChildren(el); } else { return `__h__("${el.tag}", ${genData(el, key) }, ${genChildren(el)})`; } }
genElement()函數(shù)內(nèi)部依次調(diào)用getAndRemoveAttr()函數(shù)判斷了v-for、v-if標(biāo)簽是否存在,若存在則刪除并返回表達(dá)式;隨后判斷節(jié)點(diǎn)名為template就直接進(jìn)入子節(jié)點(diǎn)解析;以上條件都不符合就返回__h__函數(shù)字符串,該字符串將使用到屬性解析和子節(jié)點(diǎn)解析。
function getAndRemoveAttr (el, attr) { let val; // 如果屬性存在,則從AST對(duì)象的attrs和attrsMap移除 if (val = el.attrsMap[attr]) { el.attrsMap[attr] = null; for (let i = 0, l = el.attrs.length; i < l; i++) { if (el.attrs[i].name === attr) { el.attrs.splice(i, 1); break; } } } return val; }v-for 和 v-if 指令解析
讓我們先看看v-for的編譯:
function genFor (el, exp) { const inMatch = exp.match(/([a-zA-Z_][w]*)s+(?:in|of)s+(.*)/); if (!inMatch) { throw new Error("Invalid v-for expression: "+ exp); } const alias = inMatch[1].trim(); exp = inMatch[2].trim(); let key = getAndRemoveAttr(el, "track-by"); // 后面用 :key 代替了 track-by if (!key) { key ="undefined"; } else if (key !== "$index") { key = alias + "["" + key + ""]"; } return `(${exp}) && (${exp}).map(function (${alias}, $index) {return ${genElement(el, key)}})`; }
該函數(shù)先進(jìn)行正則匹配,如"item in items",將解析出別名(item)和表達(dá)式(items),再去看看當(dāng)前節(jié)點(diǎn)是否含:key,如果有那就作為genElement()函數(shù)的參數(shù)解析子節(jié)點(diǎn)。舉個(gè)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/53484.html
摘要:源碼解析這邊解析的是從樹(shù)轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個(gè)語(yǔ)法樹(shù)轉(zhuǎn)函數(shù)的起點(diǎn)是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語(yǔ)法樹(shù),內(nèi)部調(diào)用函數(shù)開(kāi)始解析根節(jié)點(diǎn)容器節(jié)點(diǎn)。 通過(guò)對(duì) Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語(yǔ)法樹(shù) AST語(yǔ)法樹(shù)轉(zhuǎn)r...
摘要:通過(guò)對(duì)源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫模版字符串轉(zhuǎn)語(yǔ)法樹(shù)語(yǔ)法樹(shù)轉(zhuǎn)函數(shù)雙向綁定原理虛擬比較原理其中包含自己的理解和源碼的分析,盡量通俗易懂由于是的最早提交,所以和最新版本有很多差異,后續(xù)將陸續(xù)補(bǔ)充, 通過(guò)對(duì) Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語(yǔ)法...
摘要:通過(guò)對(duì)源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫模版字符串轉(zhuǎn)語(yǔ)法樹(shù)語(yǔ)法樹(shù)轉(zhuǎn)函數(shù)雙向綁定原理虛擬比較原理其中包含自己的理解和源碼的分析,盡量通俗易懂由于是的最早提交,所以和最新版本有很多差異,后續(xù)將陸續(xù)補(bǔ)充, 通過(guò)對(duì) Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開(kāi)始讀,準(zhǔn)備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語(yǔ)法...
閱讀 980·2021-11-24 09:39
閱讀 2736·2021-09-26 09:55
閱讀 14448·2021-08-23 09:47
閱讀 3593·2019-08-30 15:52
閱讀 863·2019-08-29 13:49
閱讀 1016·2019-08-23 18:00
閱讀 859·2019-08-23 16:42
閱讀 1655·2019-08-23 14:28