两者作用
v-if:
v-if 指令用于条件性地渲染所在元素块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。v-if 指令 可以和 v-else-if、v-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)
})