Heim > Web-Frontend > View.js > Hauptteil

Prioritätsvergleich: Was ist höher, v-for oder v-if?

青灯夜游
Freigeben: 2022-08-29 19:52:05
nach vorne
3207 Leute haben es durchsucht

Welches hat die höhere Priorität, v-for oder v-if? Im folgenden Artikel werden die Prioritäten von v-for und v-if anhand konkreter Beispiele und Quellcode erläutert.
v-forv-if的优先级,相信你看完后会茅塞顿开的。

Prioritätsvergleich: Was ist höher, v-for oder v-if?

结论

1、本身并不建议将v-for和v-if同时使用的。(学习视频分享:vue视频教程

2、vue2里面v-for比v-if的优先级更高。因为vue2在模板编译的时候会先处理v-for再处理v-if,所以生成的渲染函数会先执行循环,然后在循环里面再执行条件判断。

3、这样做带来的问题就是

对于场景1:<li v-for="user in users" v-if="user.show">

每次重新渲染的时候,都要重新遍历整个列表,其实我们只需要列表的一部分,这样做浪费性能。推荐的做法是,通过计算属性先过滤出我们需要的部分,再去渲染,更高效。

对于场景2: <li v-for="user in users" v-if="globalShow">

globalShow这个判断其实如果是false,循环并不需要执行,但是现在跟v-if一起用,不管globalShow是否是true都要执行循环,完全是浪费。推荐的做法是将v-if上移到ul容器。

4、需要注意的是,vue3的breaking change,在vue3中v-if的优先级比v-for高,所以如果同时使用的话,对于场景1,这个时候user还没有,v-if="user.show"就会报错

5、一般我们如果有用eslint,也会给我们报错,对应的规则是:vue/no-use-v-if-with-v-for

实际例子

例如:以下的模板,将会生成下面的渲染函数

<ul>
    <li v-for="user in users" v-if="user.isActive" :key="user.id">
        {{ user.name }}
    </li>
</ul>
Nach dem Login kopieren

生成的渲染函数如下

with(this) {
    return _c('ul', _l((users), function (user) {
        return (user.isActive) ? _c('li', user.name) : _e()
    }), 0)
}
Nach dem Login kopieren

从上面生成的渲染函数可以看出,会先执行_l遍历user,在里面进行条件判断

源码

处理v-if和v-for的源码

src/compiler/index.js

// 模板解析,生成ast树
const ast = parse(template.trim(), options)
if (options.optimize !== false) {
    optimize(ast, options)
}
const code = generate(ast, options)
Nach dem Login kopieren

根据ast生成代码,假如是上面的模板,生成的ast简化后如下

// 可以看出v-for和v-if都解析出来了
 ast = {
     'type': 1,
     'tag': 'ul',
     'attrsList': [],
     'attrsMap': {},
     'children': [{
     'type': 1,
     'tag': 'li',
     'attrsList': [],
     'attrsMap': {
         'v-for': 'user in users',
         'v-if': 'user.show'
     },
     // v-if解析出来的属性
     'if': 'user.show',
     'ifConditions': [{
         'exp': 'user.show',
         'block': // 指向el自身
     }],
     // v-for解析出来的属性
     'for': 'users',
     'alias': 'user',
     'iterator1': 'index',
     'parent': // 指向其父节点
     'children': [
         'type': 2,
         'expression': '_s(user)'
         'text': '{{user}}',
         'tokens': [
             {'@binding':'user'},
         ]
      ]
     }]
 }
Nach dem Login kopieren

compiler/codegen/index.js

// generate 调用 genElement
const code = ast ? genElement(ast, state) : '_c("div")'
// genElement里面的处理
if (el.staticRoot && !el.staticProcessed) {
return genStatic(el, state)
} else if (el.once && !el.onceProcessed) {
return genOnce(el, state)
// 从这可以看出来,先执行genFor,处理v-for指令,在genFor里面会递归调用genElement,继续处理v-if,genFor会将forProcessed设为true,这样下次进来的时候就不会处理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 {
// 最后这里处理标签等
const children = el.inlineTemplate ? null : genChildren(el, state, true)
code = `_c('${el.tag}'${
data ? `,${data}` : '' // data
}${
children ? `,${children}` : '' // children
})`
}

// genFor的代码
const exp = el.for // 对应上面ast的 for: users
const alias = el.alias // alias: user
// iterator1 对应v-for的(item,key,index) in items的key
// iterator2 对应的是index
// 通常我们遍历数组 key就是index
// 假如我们遍历的是对象 key就是对象的key,index就是遍历的索引
const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
el.forProcessed = true // 下次递归调用genElement的时候就不会重复处理v-for了
return `${altHelper || '_l'}((${exp}),` +
`function(${alias}${iterator1}${iterator2}){`

// 这里处理完了v-for,递归调用genElement继续处理v-if
`return ${(altGen || genElement)(el, state)}` +
'})'
Nach dem Login kopieren

最终会生成类似如下的代码返回出去

Prioritätsvergleich: Was ist höher, v-for oder v-if?

Fazit

1. Es wird nicht empfohlen, v-for und v-if gleichzeitig zu verwenden. (Teilen von Lernvideos: vue Video Tutorial)2. In vue2 hat v-for eine höhere Priorität als v-if. Da vue2 beim Kompilieren der Vorlage zuerst v-for und dann v-if verarbeitet, führt die generierte Rendering-Funktion zuerst die Schleife aus und führt dann die bedingte Beurteilung innerhalb der Schleife aus. 🎜3. Das dadurch verursachte Problem ist 🎜🎜Für Szenario 1: <li v-for="user in users" v-if="user.show">🎜🎜Every Bei jedem erneuten Rendern müssen wir die gesamte Liste erneut durchlaufen. Tatsächlich benötigen wir nur einen Teil der Liste, was zu Leistungsverlusten führt. Der empfohlene Ansatz besteht darin, die benötigten Teile durch berechnete Attribute herauszufiltern und sie dann zu rendern, was effizienter ist. 🎜🎜Für Szenario 2: <li v-for="user in users" v-if="globalShow">🎜🎜Tatsächlich ist die Schleife falsch, wenn die Beurteilung von globalShow falsch ist Muss jedoch nicht ausgeführt werden, wenn es zusammen mit v-if verwendet wird, muss die Schleife unabhängig davon ausgeführt werden, ob globalShow wahr ist oder nicht, was eine völlige Verschwendung ist. Der empfohlene Ansatz besteht darin, v-if nach oben in den ul-Container zu verschieben. 🎜🎜4. Es ist zu beachten, dass v-if für die bahnbrechende Änderung von vue3 eine höhere Priorität hat als v-for in vue3. Wenn sie also gleichzeitig verwendet werden, hat der Benutzer dies für Szenario 1 noch nicht getan Wird zu diesem Zeitpunkt verwendet, meldet v-if="user.show" einen Fehler🎜🎜5. Wenn wir eslint verwenden, wird uns im Allgemeinen auch ein Fehler gemeldet. Die entsprechende Regel lautet: vue/no-use-v -if-with-v-for🎜

Tatsächliches Beispiel

🎜Zum Beispiel: Die folgende Vorlage generiert die folgende Rendering-Funktion🎜
_l((users), function(user, index) {
    // 如果有v-if 前面就会有个条件判断,如user.isActive
    return (user.isActive) ? _c('li', user.name) : _e()
});
Nach dem Login kopieren
🎜Die generierte Rendering-Funktion lautet wie folgt 🎜rrreee🎜Wie aus der oben generierten Rendering-Funktion ersichtlich ist, wird sie zuerst ausgeführt. _l durchläuft user und führt darin eine bedingte Beurteilung durch🎜

Quellcode

🎜Verarbeitung von v-if und v-for Der Quellcode🎜🎜src/compiler/index.js🎜rrreee🎜generiert Code basierend auf ast. Wenn ja Ist die obige Vorlage, wird der generierte AST wie folgt vereinfacht 🎜rrreee🎜 (Lernvideo-Sharing: 🎜Web-Front-End-Entwicklung🎜, 🎜Grundlegendes Programmiervideo🎜)🎜

Das obige ist der detaillierte Inhalt vonPrioritätsvergleich: Was ist höher, v-for oder v-if?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!