- v-if 与 v-for简介
- v-if
- v-for
- v-if & v-for使用
- v-if 与 v-for优先级比较
- vue2 中,v-for的优先级高于v-if
- 例子进行分析
- vue3 v-if 具有比 v-for 更高的优先级
- 例子进行分析
- vue2 中,v-for的优先级高于v-if
- 总结
- 在vue2中,v-for的优先级高于v-if
- 在vue3中,v-if的优先级高于v-for
咋一听到这个题,如果自己没有试验过感觉还真容易说错,就像是会进入一个“思维误区”
就会理所当然的想如果这两个指令同时出现一个标签那是不是应该先if判断是否存在才会去渲染for的循环结构?
但实际是这样吗?
v-if 与 v-for简介
v-if
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true值的时候被渲染。
v-if是Vue.js中的一个指令,用于条件渲染,根据绑定的表达式的值的真假情况来决定是否显示或隐藏元素。
当v-if的表达式值为true时,元素会被渲染出来;当v-if的表达式值为false时,元素不会被渲染出来。
例如,下面代码中,如果isShow为true,则div元素将会被渲染,否则不会被渲染:
<template>
<div v-if="isShow">
show content
</div>
</template>
需要注意的是,v-if指令会根据表达式的值动态地添加或删除元素,因此如果有频繁的切换操作,会影响性能。
此时可以考虑使用v-show指令,它只是简单地控制元素的显示或隐藏,并没有频繁的添加或删除元素。
v-for
v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组或者对象,而 item 则是被迭代的数组元素的别名。
v-for使用 的时候,建议设置key值,并且保证每个key值是独一无二的,这便于diff算法进行优化。
v-for是Vue.js中的一个指令,用于循环渲染数组或对象的数据。
v-for的用法有两种情况:
- 遍历数组:
可以通过v-for指令循环渲染一个数组,将数组中的每个元素渲染成对应的元素或组件。语法形式为:v-for="item in array"
。
例如,下面代码中使用v-for指令循环渲染一个数组list中的每个元素:
<template>
<div>
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Orange' }
]
};
}
}
</script>
- 遍历对象:
可以通过v-for指令循环渲染一个对象的属性,将对象的属性和值渲染成对应的元素或组件。语法形式为:v-for="value, key in object"
。
例如,下面代码中使用v-for指令循环渲染一个对象info的每个属性:
<template>
<div>
<ul>
<li v-for="(value, key) in info" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
info: {
name: 'John',
age: 25,
gender: 'Male'
}
};
}
}
</script>
需要注意的是,在使用v-for时,需要为每个循环的元素或组件添加唯一的key属性,以便Vue.js能够跟踪每个节点的身份,并且在更新时进行高效的DOM操作。
更多详细内容,请微信搜索“前端爱好者
“, 戳我 查看 。
v-if & v-for使用
<ul>
<li v-for='user in users' :key='user.id'>{{user.name}}</li>
</ul>
<footer v-if='user'>{{user}}</footer>
v-if 与 v-for优先级比较
- 在vue2中,v-for的优先级高于v-if
- 在vue3中,v-if的优先级高于v-for(Vue 3.0 已经调整了v-if和v-for 的优先级,故不存在渲染性能问题。)
vue2 中,v-for的优先级高于v-if
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
官方文档:https://v2.cn.vuejs.org/v2/guide/conditional.html#v-if-%E4%B8%8E-v-for-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8
在 Vue 2 中,不推荐在同一个元素上同时使用 v-if 和 v-for,主要是由于可能引发的性能问题和逻辑混淆。当 v-if 和 v-for 结合使用时,会导致以下问题:
-
性能问题: 当 v-if 和 v-for 同时存在于同一个元素上时,Vue 会在每次循环迭代时都重新渲染和销毁元素。这可能会导致不必要的 DOM 更新和性能下降,特别是在较长的列表上。这是因为每次循环迭代都会重新计算条件,并进行 DOM 操作。
-
逻辑混淆: 同时使用 v-if 和 v-for 会增加代码的复杂性和理解难度。将条件和循环逻辑分离可以使代码更加清晰,并让开发人员更容易理解和维护。
例子进行分析
<template>
<div class="test-container">
<div v-for="(item,index) in list" v-if="item === 9" :key="item" ></div>
</div>
</template>
<script>
export default {
data(){
return {
numberArr:[1,2,3,4,5,6,7,8,9,10]
}
}
};
</script>
<style scoped>
</style>
但是本段代码实际的逻辑为
this.numberArr.map(function (item,index) {
if (item===9) {
return item
}
})
相反,最佳实践是:
将条件渲染 (v-if) 和列表渲染 (v-for) 分开处理。
可以使用计算属性或方法来处理数据,然后在模板中分别使用 v-if 和 v-for。
以下是一个示例代码:
<template>
<div>
<div v-if="showDiv" v-for="item in filteredItems" :key="item.id">
{{ item.name }}
</div>
</div>
</template>
<script>
export default {
data() {
return {
showDiv: true,
items: [
{ id: 1, name: 'Item 1', isActive: true },
{ id: 2, name: 'Item 2', isActive: false },
{ id: 3, name: 'Item 3', isActive: true }
]
}
},
computed: {
filteredItems() {
return this.items.filter(item => item.isActive);
}
}
}
</script>
在上述示例中,我们使用了计算属性 filteredItems 来过滤具有 isActive 属性的项目。
然后,我们在模板中使用 v-for 来渲染过滤后的结果,并使用 v-if 来条件性地渲染每个元素。这样可以保持逻辑的清晰和性能的优化。
vue3 v-if 具有比 v-for 更高的优先级
当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级。
官方文档:https://cn.vuejs.org/guide/essentials/list.html#v-for-with-v-if
<!--
这会抛出一个错误,因为属性 todo 此时
没有在该实例上定义
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
推荐: 在外新包装一层 再在其上使用 v-for 可以解决这个问题 (这也更加明显易读):
<template v-for="todo in todos">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
例子进行分析
<template>
<div class="test-container">
<div v-for="(item,index) in numberArr" v-if="item === 9" :key="item"></div>
</div>
</template>
<script>
export default {
data(){
return {
numberArr: [1,2,3,4,5,6,7,8,9,10] //需要遍历的数据
}
}
};
</script>
<style scoped>
</style>
由于 v-if 优先级高,导致页面并没有进行渲染,控制台报错。
以下为控制台报错信息
[Vue warn]: Property "index" was accessed during render but is not defined on instance.
但是下面这种用法控制台并不会报错但是会警告
<template>
<div class="test-container">
<ul>
<li v-for="(item, index) in objList" :key="index" v-if="item.isShow">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
objList:[
{ name: 'obj2', isShow: false },
{ name: 'obj2', isShow: true },
]
}
}
};
</script>
<style scoped>
</style>
但是这种写法也会有一个问题,无论是否符合v-if的条件都进行了报错
官方推荐的写法是这样的, 把 v-for 移动到容器元素上,例如ul,ol 或者外面包裹一层 template
<template>
<div class="test-container">
<ul>
<template v-for="(item, index) in objList" :key="index">
<li v-if="item.isShow">
{{ item.name }}
</li>
</template>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
objList:[
{ name: 'obj2', isShow: false },
{ name: 'obj2', isShow: true },
]
}
}
};
</script>
<style scoped>
</style>
但如果想要有条件地跳过循环的执行,那么可以将v-if置于外层元素或者template上。
例如这样:
<template>
<div class="test-container">
<ul v-if="objList.length">
<li v-for="(item, index) in objList" :key="index">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
objList:[
{ name: 'obj2', isShow: false },
{ name: 'obj2', isShow: true },
]
}
}
};
</script>
<style scoped>
</style>
总结
在vue2中,v-for的优先级高于v-if
Vue 会在每次循环迭代时都重新渲染和销毁元素。
v-for比v-if优先级更高(可以说清结论的来源更好)。
如果同时出现在同一个标签上,则每次渲染都会先执行循环再进行条件判断,会造成较大的性能浪费。
解决办法有两种:
- 先在外层套一个template来放置v-if,再嵌套v-for。
- 借助computed计算属性代替v-if。
在vue3中,v-if的优先级高于v-for
注:Vue 3.0 已经调整了v-if和v-for 的优先级,故不存在渲染性能问题。
参考文档
- https://www.nowcoder.com/discuss/513503986318696448
- https://baijiahao.baidu.com/s?id=1766197354040903874&wfr=spider&for=pc