成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Vue源碼解析:AST語(yǔ)法樹(shù)轉(zhuǎn)render函數(shù)

trilever / 641人閱讀

摘要:源碼解析這邊解析的是從樹(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)render函數(shù)

Vue雙向綁定原理

Vue虛擬dom比較原理

其中包含自己的理解和源碼的分析,盡量通俗易懂!由于是2.0的最早提交,所以和最新版本有很多差異、bug,后續(xù)將陸續(xù)補(bǔ)充,敬請(qǐng)諒解!包含中文注釋的Vue源碼已上傳...

開(kāi)始

今天要說(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

相關(guān)文章

  • Vue源碼解析AST語(yǔ)法樹(shù)轉(zhuǎn)render函數(shù)

    摘要:源碼解析這邊解析的是從樹(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...

    Karuru 評(píng)論0 收藏0
  • Vue源碼解析:模版字符串轉(zhuǎn)AST語(yǔ)法樹(shù)

    摘要:通過(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ǔ)法...

    chengjianhua 評(píng)論0 收藏0
  • Vue源碼解析:模版字符串轉(zhuǎn)AST語(yǔ)法樹(shù)

    摘要:通過(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ǔ)法...

    王偉廷 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<