人妻精品在线观看一区二区三区,蜜臀av精品一区二区三区网站,中文一区二区三区亚洲欧美,熟女人妇精品一区二区,人妻av在线观看视频,欧美日韩国产三级精品网站,黄色免费网站直接进入,超碰公开福利正在播放,国产毛片乡下农村妇女毛片

vue優(yōu)先級比較:為什么v-for比v-if高

來源:php中文網(wǎng) | 2023-03-14 19:48:38 |

vue為什么v-for的優(yōu)先級比v-if的高?下面本篇文章就通過分析源碼去解答一下這個問題,希望對大家有所幫助!


(資料圖片)

有時候有些面試中經(jīng)常會問到v-forv-if誰的優(yōu)先級高,這里就通過分析源碼去解答一下這個問題。

下面的內(nèi)容是在 當(dāng)我們談及v-model,我們在討論什么?的基礎(chǔ)上分析的,所以閱讀下面內(nèi)容之前可先看這篇文章。

繼續(xù)從編譯出發(fā)

以下面的例子出發(fā)分析:

new Vue({    el:"#app",    template:`        <ul>            <li v-for="(item,index) in items" v-if="index!==0">                {{item}}            </li>        </ul>    `})

從上篇文章可以知道,編譯有三個步驟

parse: 解析模板字符串生成 AST語法樹optimize: 優(yōu)化語法樹,主要時標(biāo)記靜態(tài)節(jié)點,提高更新頁面的性能 【相關(guān)推薦:vuejs視頻教程、web前端開發(fā)】codegen: 生成js代碼,主要是render函數(shù)和staticRenderFns函數(shù)

我們再次順著這三個步驟對上述例子進(jìn)行分析。

parse

parse過程中,會對模板使用大量的正則表達(dá)式去進(jìn)行解析。開頭的例子會被解析成以下AST節(jié)點:

// 其實ast有很多屬性,我這里只展示涉及到分析的屬性ast = {  "type": 1,  "tag": "ul",  "attrsList": [],  attrsMap: {},  "children": [{    "type": 1,    "tag": "li",    "attrsList": [],    "attrsMap": {      "v-for": "(item,index) in data",      "v-if": "index!==0"     },     // v-if解析出來的屬性    "if": "index!==0",    "ifConditions": [{      "exp": "index!==0",      "block": // 指向el自身    }],    // v-for解析出來的屬性    "for": "items",    "alias": "item",    "iterator1": "index",    "parent": // 指向其父節(jié)點    "children": [      "type": 2,      "expression": "_s(item)"      "text": "{{item}}",      "tokens": [        {"@binding":"item"},      ]    ]  }]}

對于v-for指令,除了記錄在attrsMapattrsList,還會新增for(對應(yīng)要遍歷的對象或數(shù)組),aliasiterator1,iterator2對應(yīng)v-for指令綁定內(nèi)容中的第一,第二,第三個參數(shù),開頭的例子沒有第三個參數(shù),因此沒有iterator2屬性。

對于v-if指令,把v-if指令中綁定的內(nèi)容取出放在if中,與此同時初始化ifConditions屬性為數(shù)組,然后往里面存放對象:{exp,block},其中exp存放v-if指令中綁定的內(nèi)容,block指向el。

optimize過程在此不做分析,因為本例子沒有靜態(tài)節(jié)點。

codegen

上一篇文章從const code = generate(ast, options)開始分析過其生成代碼的過程,generate內(nèi)部會調(diào)用genElement用來解析el,也就是AST語法樹。我們來看一下genElement的源碼:

export function genElement (el: ASTElement, state: CodegenState): string {  if (el.parent) {    el.pre = el.pre || el.parent.pre  }  if (el.staticRoot && !el.staticProcessed) {    return genStatic(el, state)  } else if (el.once && !el.onceProcessed) {    return genOnce(el, state)  // 其實從此處可以初步知道為什么v-for優(yōu)先級比v-if高,  // 因為解析ast樹生成渲染函數(shù)代碼時,會先解析ast樹中涉及到v-for的屬性  // 然后再解析ast樹中涉及到v-if的屬性  // 而且genFor在會把el.forProcessed置為true,防止重復(fù)解析v-for相關(guān)屬性  } else if (el.for && !el.forProcessed) {    return genFor(el, state)  } else if (el.if && !el.ifProcessed) {    return genIf(el, state)  } else if (el.tag === "template" && !el.slotTarget && !state.pre) {    return genChildren(el, state) || "void 0"  } else if (el.tag === "slot") {    return genSlot(el, state)  } else {    // component or element    let code    if (el.component) {      code = genComponent(el.component, el, state)    } else {      let data      if (!el.plain || (el.pre && state.maybeComponent(el))) {        data = genData(el, state)      }      const children = el.inlineTemplate ? null : genChildren(el, state, true)      code = `_c("${el.tag}"${        data ? `,${data}` : "" // data      }${        children ? `,${children}` : "" // children      })`    }    // module transforms    for (let i = 0; i < state.transforms.length; i++) {      code = state.transforms[i](el, code)    }    return code  }}

接下來依次看看genForgenIf的函數(shù)源碼:

export function genFor (el, state , altGen, altHelper) {  const exp = el.for  const alias = el.alias  const iterator1 = el.iterator1 ? `,${el.iterator1}` : ""  const iterator2 = el.iterator2 ? `,${el.iterator2}` : ""  el.forProcessed = true // avoid recursion  return `${altHelper || "_l"}((${exp}),` +     `function(${alias}${iterator1}${iterator2}){` +      `return ${(altGen || genElement)(el, state)}` + //遞歸調(diào)用genElement    "})"}

在我們的例子里,當(dāng)他處理liast樹時,會先調(diào)用genElement,處理到for屬性時,此時forProcessed為虛值,此時調(diào)用genFor處理li樹中的v-for相關(guān)的屬性。然后再調(diào)用genElement處理li樹,此時因為forProcessedgenFor中已被標(biāo)記為true。因此genFor不會被執(zhí)行,繼而執(zhí)行genIf處理與v-if相關(guān)的屬性。

export function genIf (el,state,altGen,altEmpty) {  el.ifProcessed = true // avoid recursion  // 調(diào)用genIfConditions主要處理el.ifConditions屬性  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)}function genIfConditions (conditions, state, altGen, altEmpty) {  if (!conditions.length) {    return altEmpty || "_e()" // _e用于生成空VNode  }  const condition = conditions.shift()  if (condition.exp) { //condition.exp即v-if綁定值,例子中則為"index!==0"    // 生成一段帶三目運算符的js代碼字符串    return `(${condition.exp})?${       genTernaryExp(condition.block)    }:${      genIfConditions(conditions, state, altGen, altEmpty)    }`  } else {    return `${genTernaryExp(condition.block)}`  }  // v-if with v-once should generate code like (a)?_m(0):_m(1)  function genTernaryExp (el) {    return altGen      ? altGen(el, state)      : el.once        ? genOnce(el, state)        : genElement(el, state)  }}

參考 前端進(jìn)階面試題詳細(xì)解答

最后,經(jīng)過codegen生成的js代碼如下:

function render() {  with(this) {    return _c("ul", _l((items), function (item, index) {      return (index !== 0) ? _c("li") : _e()    }), 0)  }}

其中:

_c: 調(diào)用 createElement去創(chuàng)建 VNode

_l: renderList函數(shù),主要用來渲染列表

_e: createEmptyVNode函數(shù),主要用來創(chuàng)建空VNode

總結(jié)

為什么v-for的優(yōu)先級比v-if的高?總結(jié)來說是編譯有三個過程,parse->optimize->codegen。在codegen過程中,會先解析AST樹中的與v-for相關(guān)的屬性,再解析與v-if相關(guān)的屬性。除此之外,也可以知道Vuev-forv-if是怎么處理的。

(學(xué)習(xí)視頻分享:vuejs入門教程、編程基礎(chǔ)視頻)

以上就是vue優(yōu)先級比較:為什么v-for比v-if高的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!

關(guān)鍵詞: