真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

vue中v-for比v-if高的原因是什么

本篇內(nèi)容介紹了“vue中v-for比v-if高的原因是什么”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

西青網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,西青網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為西青成百上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營(yíng)銷(xiāo)網(wǎng)站建設(shè)要多少錢(qián),請(qǐng)找那個(gè)售后服務(wù)好的西青做網(wǎng)站的公司定做!

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

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

new Vue({
    el:'#app',
    template:`
        
                                 {{item}}                      
    ` })

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

  • parse: 解析模板字符串生成 AST語(yǔ)法樹(shù)

  • optimize: 優(yōu)化語(yǔ)法樹(shù),主要時(shí)標(biāo)記靜態(tài)節(jié)點(diǎn),提高更新頁(yè)面的性能

  • codegen: 生成js代碼,主要是render函數(shù)和staticRenderFns函數(shù)

我們?cè)俅雾樦@三個(gè)步驟對(duì)上述例子進(jìn)行分析。

parse

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

// 其實(shí)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解析出來(lái)的屬性
    'if': 'index!==0',
    'ifConditions': [{
      'exp': 'index!==0',
      'block': // 指向el自身
    }],
    // v-for解析出來(lái)的屬性
    'for': 'items',
    'alias': 'item',
    'iterator1': 'index',

    'parent': // 指向其父節(jié)點(diǎn)
    'children': [
      'type': 2,
      'expression': '_s(item)'
      'text': '{{item}}',
      'tokens': [
        {'@binding':'item'},
      ]
    ]
  }]
}

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

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

optimize過(guò)程在此不做分析,因?yàn)楸纠記](méi)有靜態(tài)節(jié)點(diǎn)。

codegen

上一篇文章從const code = generate(ast, options)開(kāi)始分析過(guò)其生成代碼的過(guò)程,generate內(nèi)部會(huì)調(diào)用genElement用來(lái)解析el,也就是AST語(yǔ)法樹(shù)。我們來(lái)看一下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)
  // 其實(shí)從此處可以初步知道為什么v-for優(yōu)先級(jí)比v-if高,
  // 因?yàn)榻馕鯽st樹(shù)生成渲染函數(shù)代碼時(shí),會(huì)先解析ast樹(shù)中涉及到v-for的屬性
  // 然后再解析ast樹(shù)中涉及到v-if的屬性
  // 而且genFor在會(huì)把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
  }
}

接下來(lái)依次看看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樹(shù)時(shí),會(huì)先調(diào)用genElement,處理到for屬性時(shí),此時(shí)forProcessed為虛值,此時(shí)調(diào)用genFor處理li樹(shù)中的v-for相關(guān)的屬性。然后再調(diào)用genElement處理li樹(shù),此時(shí)因?yàn)?code>forProcessed在genFor中已被標(biāo)記為true。因此genFor不會(huì)被執(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'
    // 生成一段帶三目運(yùn)算符的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)過(guò)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ù),主要用來(lái)渲染列表

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

“vue中v-for比v-if高的原因是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


網(wǎng)頁(yè)題目:vue中v-for比v-if高的原因是什么
標(biāo)題來(lái)源:http://weahome.cn/article/pecjed.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部