The two most used directives in vue.js are V-if and V-for, so we might want to use them together. While this is not officially recommended, it is sometimes necessary, and here’s how it works:

  • In Vue 2.x, used simultaneously on an elementv-ifv-forWhen,v-forWill take precedence.
  • In vue 3.x,v-ifAlways take precedence overv-forTo take effect.

Comparative study

Let’s take a look at a simple example. Suppose we want to implement a minimalist todoList effect:

We have a todoList:

const todoList = [
  {
    id: 0.task: 'eat'.done: true}, {id: 1.task: 'sleep'.done: false}, {id: 2.task: 'take a shower'.done: true,},/ /... .
];
Copy the code

In VUe2, v-for has a higher priority than V-IF. We can implement it as follows:

<ul>
  <! -- In vue2, v-for has higher priority than v-if -->
  <li v-for="item in todoList" v-if=! "" item.done" :class="{todo: ! item.done}" :key="item.id">
    <span>{{item.task}}</span>
  </li>
</ul>

<ul>
  <li v-for="item in todoList" v-if="item.done" :class="{finished: item.done}" :key="item.id">
    <span>{{item.task}}</span>
  </li>
</ul>
Copy the code

In vue3, v-for and V-if cannot be placed on the same element as vue2, because v-if has a higher priority than V-for. In VUe3, v-for and V-if cannot be placed on the same element as VUe2.

<ul>
  <template v-for="item in list" :key="item.id">
    <li v-if=! "" item.done" :class="{todo: ! item.done}">
      <span>{{item.task}}</span>
    </li>
  </template>
</ul>
<ul>
  <template v-for="item in list" :key="item.id">
    <li v-if="item.done" :class="{finished: item.done}">
      <span>{{item.task}}</span>
    </li>
  </template>
</ul>
Copy the code

It can be seen that if v-if and v-for are used on the same element in vue2. X, they are not directly compatible in vue3.

Best practices

For the use of V-if and V-for, we are officially advised to use the calculated attribute to handle, which not only improves performance, but also can be compatible with vue3. X, let’s look at the implementation of the calculated attribute:

Template section:

<div id="app">
  <! -- Best Practices -->
  <ul class="todo-list">
    <li v-for="item in todos" class="todo" :key="item.id">
      <span>{{item.task}}</span>
    </li>
  </ul>

  <ul v-if="showFinished">
    <li v-for="item in finished" :key="item.id" class="finished">
      <span>{{item.task}}</span>
    </li>
  </ul>

  <p>The show finished?<input type="checkbox" v-model="showFinished" />
    {{showFinished ? 'yes' : 'no'}}
  </p>
</div>
Copy the code

Js:

// vue3.x
Vue.createApp({
  data() {
    return {
      msg: 'Todo List'.showFinished: true.list: todoList,
    };
  },
  computed: {
    finished() {
      return todoList.filter(t= > t.done);
    },
    todos() {
      return todoList.filter(t= >! t.done); }, }, }).mount('#app');

// vue2.x
new Vue({
  el: '#app'.data() {
    return {
      msg: 'Todo List'.showFinished: true.list: todoList,
    };
  },
  computed: {
    finished() {
      return todoList.filter(t= > t.done);
    },
    todos() {
      return todoList.filter(t= >! t.done); ,}}});Copy the code

Click to view: VUe3 example, VUe2 example

conclusion

  1. Vue2. Xv-forPriority overv-if, vue3.x on the contrary;
  2. Avoid using the same element at the same timev-ifandv-for, it is recommended to use computed attributes instead.