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!
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.
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
Mari analisa contoh di atas dengan mengikuti tiga langkah ini sekali lagi.
parse Semasa proses, sejumlah besar ungkapan biasa digunakan untuk menghuraikan templat. Contoh pada permulaan akan dihuraikan ke dalam nod AST
berikut:
// 其实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': // 指向其父节点 'children': [ 'type': 2, 'expression': '_s(item)' 'text': '{{item}}', 'tokens': [ {'@binding':'item'}, ] ] }] }
Untuk arahan v-for
, selain direkodkan dalam attrsMap
dan attrsList
, <🎜 baharu > (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-for
Properties. iterator2
, 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.
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 === '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 } }
dan genFor
: genIf
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)}` + //递归调用genElement '})' }
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
li
Atribut 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 || '_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) } }
Jawapan terperinci kepada soalan temuduga lanjutan bahagian hadapan
Akhir sekali, kod js yang dijana olehcodegen adalah seperti berikut:
function render() { with(this) { return _c('ul', _l((items), function (item, index) { return (index !== 0) ? _c('li') : _e() }), 0) } }
: Panggil _c
untuk mencipta createElement
VNode
: _l
Fungsi, terutamanya digunakan untuk memaparkan senarai renderList
: _e
Fungsi, terutamanya digunakan untuk membuat kosong createEmptyVNode
VNode
->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
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!