Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Interviewer: Why are v-if and v-for not recommended in Vue?


May 30, 2021 Article blog



 Interviewer: Why are v-if and v-for not recommended in Vue?1

First, the role

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>

Second, priority

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

Third, note

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
    })
  }
}