May 30, 2021 Article blog
The v-if directive is used to conditionally render a piece of content. This content is rendered only when the expression of the instruction returns a true value
The v-for instruction renders a list based on an array. The v-for directive requires a special syntax in the form of item in items, where items are arrays or objects of the source data, and items are aliases of the array elements that are iterative
At v-for, it is recommended to set the key value and ensure that each key value is unique, which makes it easy for the diff algorithm to optimize
Both are used in usage
<Modal v-if="isShow" />
<li v-for="item in items" :key="item.id">
{{ item.label }}
</li>
Both v-if and v-for are instructions in the vue template system
When the vue template is compiled, the instruction system is converted into an executable render function
Example Write a p label that uses both v-if and v-for
<div id="app">
<p v-if="isShow" v-for="item in items">
{{ item.title }}
</p>
</div>
Create a vue instance that holds isShow and items data
const app = new Vue({
el: "#app",
data() {
return {
items: [
{ title: "foo" },
{ title: "baz" }]
}
},
computed: {
isShow() {
return this.items && this.items.length > 0
}
}
})
The code for the template instruction is generated in the render function, which is rendered through app.$options.render
ƒ anonymous() {
with (this) { return
_c('div', { attrs: { "id": "app" } },
_l((items), function (item)
{ return (isShow) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e() }), 0) }
}
_l is a list rendering function of vue, and an if judgment is made inside the function
Preliminary conclusion: v-for priority is higher than v-if
Then place v-for and v-if on different labels
<div id="app">
<template v-if="isShow">
<p v-for="item in items">{{item.title}}</p>
</template>
</div>
Then output the render function
ƒ anonymous() {
with(this){return
_c('div',{attrs:{"id":"app"}},
[(isShow)?[_v("\n"),
_l((items),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}
That's when we can see that v-for and v-if work on different labels, making judgments before rendering the list
Let's look at the vue source code below
Source location: svue-dev,src-compiler-codegen-index.js
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)
} 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
...
}
V-for is the first to make a judgment when making an if judgment
Final conclusion: v-for takes precedence over v-if
1. Never use v-if and v-for on the same element at the same time, resulting in performance waste (every rendering is looped before conditional judgment)
2. If this is avoided, nest template (page rendering does not generate dom nodes) at the outer layer, make v-if judgments at this layer, and then loop v-for internally
<template v-if="isShow">
<p v-for="item in items">
</template>
3. If the condition appears inside the loop, you can filter out items that do not need to be displayed in advance by calculating the property computed
computed: {
//过滤出满足条件后的数据再渲染
items: function() {
return this.list.filter(function (item) {
return item.isShow
})
}
}