摘要:源碼解析這邊解析的是從樹轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉(zhuǎn)函數(shù)的起點是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語法樹,內(nèi)部調(diào)用函數(shù)開始解析根節(jié)點容器節(jié)點。
開始通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫:
模版字符串轉(zhuǎn)AST語法樹
AST語法樹轉(zhuǎn)render函數(shù)
Vue雙向綁定原理
Vue虛擬dom比較原理
其中包含自己的理解和源碼的分析,盡量通俗易懂!由于是2.0的最早提交,所以和最新版本有很多差異、bug,后續(xù)將陸續(xù)補充,敬請諒解!包含中文注釋的Vue源碼已上傳...
今天要說的代碼全在codegen文件夾中,在說實現(xiàn)原理前,還是先看個簡單的例子!
{{msg}}
上述類名為container的元素節(jié)點包含5個子節(jié)點(其中3個是換行文本節(jié)點),轉(zhuǎn)化成的AST語法樹:
AST語法樹轉(zhuǎn)的render函數(shù)長這樣:
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é)點的指令進行解析。
看下render函數(shù),它是由with函數(shù)包裹(為了改變作用域),要用的時候直接_render.call(vm);另外就是__h__函數(shù),這個后面會說到,這個函數(shù)用于元素節(jié)點的解析,接收3個參數(shù):元素節(jié)點標簽名,節(jié)點數(shù)據(jù),子節(jié)點數(shù)據(jù)。這個函數(shù)最后返回的就是虛擬dom了,不過今天先不深究,先說如何生成這樣的render函數(shù),主要是v-if、v-for、v-bind、v-on等指令的解析。
源碼解析這邊解析的是從AST樹轉(zhuǎn)換成render函數(shù)部分的源碼,由于vue2.0第一次提交的源碼這部分不全,故做了部分更新,代碼全在codegen文件夾中。
入口整個AST語法樹轉(zhuǎn)render函數(shù)的起點是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語法樹,內(nèi)部調(diào)用genElement()函數(shù)開始解析根節(jié)點(容器節(jié)點)。genElement()函數(shù)用于解析元素節(jié)點,它接收兩個參數(shù):AST對象和節(jié)點標識(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標簽是否存在,若存在則刪除并返回表達式;隨后判斷節(jié)點名為template就直接進入子節(jié)點解析;以上條件都不符合就返回__h__函數(shù)字符串,該字符串將使用到屬性解析和子節(jié)點解析。
function getAndRemoveAttr (el, attr) { let val; // 如果屬性存在,則從AST對象的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ù)先進行正則匹配,如"item in items",將解析出別名(item)和表達式(items),再去看看當前節(jié)點是否含:key,如果有那就作為genElement()函數(shù)的參數(shù)解析子節(jié)點。舉個
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/53484.html
摘要:源碼解析這邊解析的是從樹轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉(zhuǎn)函數(shù)的起點是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語法樹,內(nèi)部調(diào)用函數(shù)開始解析根節(jié)點容器節(jié)點。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法樹 AST語法樹轉(zhuǎn)r...
摘要:通過對源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬第一次提交開始讀,準備陸續(xù)寫模版字符串轉(zhuǎn)語法樹語法樹轉(zhuǎn)函數(shù)雙向綁定原理虛擬比較原理其中包含自己的理解和源碼的分析,盡量通俗易懂由于是的最早提交,所以和最新版本有很多差異,后續(xù)將陸續(xù)補充, 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法...
摘要:通過對源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬第一次提交開始讀,準備陸續(xù)寫模版字符串轉(zhuǎn)語法樹語法樹轉(zhuǎn)函數(shù)雙向綁定原理虛擬比較原理其中包含自己的理解和源碼的分析,盡量通俗易懂由于是的最早提交,所以和最新版本有很多差異,后續(xù)將陸續(xù)補充, 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法...
閱讀 981·2021-11-24 09:39
閱讀 2739·2021-09-26 09:55
閱讀 14713·2021-08-23 09:47
閱讀 3595·2019-08-30 15:52
閱讀 863·2019-08-29 13:49
閱讀 1016·2019-08-23 18:00
閱讀 859·2019-08-23 16:42
閱讀 1656·2019-08-23 14:28