浅谈vue2和vue3 v-for与v-if为何不建议并用的问题

319 阅读2分钟

两者作用

v-if:

v-if 指令用于条件性地渲染所在元素块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。v-if 指令 可以和 v-else-ifv-else 指令配合使用,使用逻辑和 JavaScript 中的 if...else if... else 一致, 一层一层向下判断,判断条件是否符合,符合则渲染,不符合则继续判断,直到 else 无需判断直接渲染!

v-for:

v-for 指令 可以接收一个 数组 / 整数 / 对象 来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组或者对象,而 item 则是被迭代的数组元素的别名。

两者优先级

在2.x中,对同一个元素使用v-if和v-for时,v-for优先。

在3.x中,v-if的优先级总是高于v-for。

使用注意事项

文档中都写道。由于语法模糊,建议避免在同一个元素上同时使用这两种方法。

vue2中

由于在2.x中,对同一个元素使用v-if和v-for时,v-for优先。当循环的元素过多积累起来就会,先执行v-for,后发现v-if是false,刚循环创建完元素又要删掉,带来性能浪费(县循环再条件判断)

vue3中

v-for 和 v-if:
由于隐式优先级的原因,不建议对同一个元素使用v-if和v-for.

1、当它们存在同一个节点上时,v-if的优先级高于v-for。这就意味着v-if条件不能访问v-for作用域中的变量:

<li v-for="todo in todos" v-if="!todo.isComplete">
    {{ todo.name }}
</li>

这种情况就是会直接报错,找不到Cannot read properties of undefined (reading 'isComplete'),对于todo这个值v-if是拿不到的,因为v-if在v3.x中是找不到的。

由于在3.x中,v-if的优先级总是高于v-for,v-if条件不能访问v-for作用域中的变量,所以不推荐两者一起使用。

解决办法

  • 用template
<tempalte v-for="todo in todos">
    <li v-if="!todo.isComplete">
        {{ todo.name }}
    </li>
</tempalte>
  • computed
<li v-for="todo in isNotCompleteList" v-if="!todo.isComplete">
    {{ todo.name }}
</li>

// vue2
computed: {
    isNotCompleteList() {
        return todos.filter(v => !todo.isComplete)
    }
}

// vue3
import { computed } from 'vue'

const isNotCompleteList = computed(() => {
  return todos.filter(v => !todo.isComplete)
})