Rumah >hujung hadapan web >View.js >Perbandingan keutamaan Vue: mengapa v-for lebih tinggi daripada v-if

Perbandingan keutamaan Vue: mengapa v-for lebih tinggi daripada v-if

青灯夜游
青灯夜游ke hadapan
2023-03-14 19:44:191673semak imbas

Mengapa vue mempunyai keutamaan yang lebih tinggi daripada v-if untuk v-for? Artikel berikut akan menjawab soalan ini dengan menganalisis kod sumber saya harap ia akan membantu semua orang!

Perbandingan keutamaan Vue: mengapa v-for lebih tinggi daripada v-if

Kadangkala dalam beberapa temu bual, kami sering bertanya siapa yang mempunyai keutamaan yang lebih tinggi, v-for atau v-if Di sini kami akan menjawab soalan ini dengan menganalisis kod sumber.

Kandungan berikut dianalisis berdasarkan Apabila kita bercakap tentang v-model, apa yang kita bincangkan?, jadi anda boleh membaca artikel ini sebelum membaca kandungan berikut.

Teruskan bermula dengan kompilasi

Mari kita mulakan dengan contoh berikut:

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

Seperti yang anda tahu daripada artikel sebelum ini, terdapat tiga langkah untuk menyusun

  • menghuraikan: menghuraikan rentetan templat untuk menjana pepohon sintaks AST
  • optimumkan: mengoptimumkan pepohon sintaks, terutamanya menandakan nod statik untuk meningkatkan kemas kini prestasi Halaman [Cadangan berkaitan: tutorial video vuejs, pembangunan bahagian hadapan web]
  • codegen: Jana js, terutamanya fungsi render dan fungsi staticRenderFns

Mari analisa contoh di atas dengan mengikuti tiga langkah ini sekali lagi.

parse

parse Semasa proses, sejumlah besar ungkapan biasa digunakan untuk menghuraikan templat. Contoh pada permulaan akan dihuraikan ke dalam nod AST berikut:

// 其实ast有很多属性,我这里只展示涉及到分析的属性
ast = {
  &#39;type&#39;: 1,
  &#39;tag&#39;: &#39;ul&#39;,
  &#39;attrsList&#39;: [],
  attrsMap: {},
  &#39;children&#39;: [{
    &#39;type&#39;: 1,
    &#39;tag&#39;: &#39;li&#39;,
    &#39;attrsList&#39;: [],
    &#39;attrsMap&#39;: {
      &#39;v-for&#39;: &#39;(item,index) in data&#39;,
      &#39;v-if&#39;: &#39;index!==0&#39;
     },
     // v-if解析出来的属性
    &#39;if&#39;: &#39;index!==0&#39;,
    &#39;ifConditions&#39;: [{
      &#39;exp&#39;: &#39;index!==0&#39;,
      &#39;block&#39;: // 指向el自身
    }],
    // v-for解析出来的属性
    &#39;for&#39;: &#39;items&#39;,
    &#39;alias&#39;: &#39;item&#39;,
    &#39;iterator1&#39;: &#39;index&#39;,

    &#39;parent&#39;: // 指向其父节点
    &#39;children&#39;: [
      &#39;type&#39;: 2,
      &#39;expression&#39;: &#39;_s(item)&#39;
      &#39;text&#39;: &#39;{{item}}&#39;,
      &#39;tokens&#39;: [
        {&#39;@binding&#39;:&#39;item&#39;},
      ]
    ]
  }]
}

Untuk arahan v-for, selain direkodkan dalam attrsMap dan attrsList, (sepadan dengan objek traversal atau tatasusunan), for, alias, iterator1 sepadan dengan parameter pertama, kedua dan ketiga dalam kandungan mengikat arahan iterator2 Contoh pada permulaan tidak mempunyai a parameter ketiga, jadi tiada v-forProperties. iterator2

Untuk arahan

, keluarkan kandungan yang terikat dalam arahan v-if dan letakkan dalam v-if Pada masa yang sama, mulakan atribut if kepada tatasusunan, dan kemudian simpan objek di dalamnya: ifConditions , di mana {exp,block} menyimpan kandungan yang terikat dalam perintah exp dan v-if menunjuk ke block. el

optimumkan Proses ini tidak dianalisis di sini kerana tiada nod statik dalam contoh ini.

codegen

Artikel sebelum ini menganalisis proses penjanaan kod bermula daripada

const code = generate(ast, options) secara dalaman memanggil generate untuk menghuraikan genElement, iaitu pokok sintaks el. Mari kita lihat kod sumber 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优先级比v-if高,
  // 因为解析ast树生成渲染函数代码时,会先解析ast树中涉及到v-for的属性
  // 然后再解析ast树中涉及到v-if的属性
  // 而且genFor在会把el.forProcessed置为true,防止重复解析v-for相关属性
  } else if (el.for && !el.forProcessed) {
    return genFor(el, state)
  } else if (el.if && !el.ifProcessed) {
    return genIf(el, state)

  } else if (el.tag === &#39;template&#39; && !el.slotTarget && !state.pre) {
    return genChildren(el, state) || &#39;void 0&#39;
  } else if (el.tag === &#39;slot&#39;) {
    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(&#39;${el.tag}&#39;${        data ? `,${data}` : &#39;&#39; // data      }${        children ? `,${children}` : &#39;&#39; // children      })`
    }
    // module transforms
    for (let i = 0; i < state.transforms.length; i++) {
      code = state.transforms[i](el, code)
    }
    return code
  }
}
Seterusnya, mari kita lihat kod sumber fungsi

dan genFor: genIf

export function genFor (el, state , altGen, altHelper) {
  const exp = el.for
  const alias = el.alias
  const iterator1 = el.iterator1 ? `,${el.iterator1}` : &#39;&#39;
  const iterator2 = el.iterator2 ? `,${el.iterator2}` : &#39;&#39;

  el.forProcessed = true // avoid recursion
  return `${altHelper || &#39;_l&#39;}((${exp}),` + 
    `function(${alias}${iterator1}${iterator2}){` +
      `return ${(altGen || genElement)(el, state)}` + //递归调用genElement
    &#39;})&#39;
}
Dalam contoh kami, Apabila ia memproses

pokok li, ia akan memanggil ast terlebih dahulu Apabila atribut genElement diproses, for ialah nilai maya pada masa ini, forProcessed dipanggil untuk memproses pokok genFor liAtribut yang berkaitan. Kemudian panggil v-for untuk memproses pokok genElement, kerana li telah ditanda sebagai forProcessed dalam genFor. Oleh itu, true tidak akan dilaksanakan, dan kemudian genFor akan dilaksanakan untuk memproses atribut yang berkaitan dengan genIf. v-if

export function genIf (el,state,altGen,altEmpty) {
  el.ifProcessed = true // avoid recursion
  // 调用genIfConditions主要处理el.ifConditions属性
  return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
}

function genIfConditions (conditions, state, altGen, altEmpty) {
  if (!conditions.length) {
    return altEmpty || &#39;_e()&#39; // _e用于生成空VNode
  }

  const condition = conditions.shift()
  if (condition.exp) { //condition.exp即v-if绑定值,例子中则为&#39;index!==0&#39;
    // 生成一段带三目运算符的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)
  }
}
Rujuk

Jawapan terperinci kepada soalan temuduga lanjutan bahagian hadapan

Akhir sekali, kod js yang dijana oleh

codegen adalah seperti berikut:

function render() {
  with(this) {
    return _c(&#39;ul&#39;, _l((items), function (item, index) {
      return (index !== 0) ? _c(&#39;li&#39;) : _e()
    }), 0)
  }
}
Antaranya:

  • : Panggil _c untuk mencipta createElementVNode

  • : _l Fungsi, terutamanya digunakan untuk memaparkan senarai renderList

  • : _eFungsi, terutamanya digunakan untuk membuat kosong createEmptyVNodeVNode

Ringkasan

Mengapa v-for mempunyai keutamaan yang lebih tinggi daripada v-if? Secara ringkasnya, terdapat tiga proses penyusunan,

->parse->optimize. Dalam proses codegen, atribut yang berkaitan dengan codegen dalam pepohon AST akan dihuraikan terlebih dahulu, dan kemudian atribut yang berkaitan dengan v-for akan dihuraikan. Selain itu, anda juga boleh mengetahui cara v-if mengendalikan Vue dan v-for. v-if

(Mempelajari perkongsian video:

tutorial pengenalan vuejs, Video pengaturcaraan asas)

Atas ialah kandungan terperinci Perbandingan keutamaan Vue: mengapa v-for lebih tinggi daripada v-if. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam