原文网址:Vue--v-if和v-for不能同时使用--原因/解决方案/实例_IT利刃出鞘的博客-CSDN博客
简介
简介
本文介绍v-if和v-for不要同时使用的原因及解决方案。
官网
条件渲染 — Vue.js
风格指南 — Vue.js
原因与解决方案
说明
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
vue官方着重强调:永远不要把 v-if 和 v-for 同时用在同一个元素上。
v-if和v-for不能同时使用的原因
v-for比v-if优先级高,每一次都需要遍历整个数组,造成不必要的计算,影响性能。即使100个list中只需要使用一个数据,也会循环整个数组。
解决方案
场景1:每项都有自己的状态
例:v-for="user in users" v-if="user.isActive"。将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
场景2:有公共的状态
例:v-for="user in users" v-if="shouldShowUsers"。将 v-if 移动至外部容器元素上 (比如 ul、ol)。
示例1:每项都有自己的状态
公共代码
路由(router/index.js)
import Vue from 'vue'
import Router from 'vue-router'
import Demo from "../views/Demo";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/demo',
name: 'Demo',
component: Demo,
}
],
})
反例
代码
Demo.vue
<template>
<div class="hello">
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.userId"
>
{{user.userName}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Demo',
data () {
return {
users: [
{
userId: 1,
userName: 'Tony1',
isActive: true
},
{
userId: 2,
userName: 'Tony2',
isActive: false
},
{
userId: 3,
userName: 'Tony3',
isActive: true
}
]
}
},
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/demo
总结
当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,所以上述模板会进行如下运算:
this.users.map(function (user) {
if (user.isActive) {
return user.name
}
})
因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表。
好例子
代码
Demo.vue
<template>
<div class="hello">
<ul>
<li
v-for="user in activeUsers"
:key="user.userId"
>
{{user.userName}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Demo',
data () {
return {
users: [
{
userId: 1,
userName: 'Tony1',
isActive: true
},
{
userId: 2,
userName: 'Tony2',
isActive: false
},
{
userId: 3,
userName: 'Tony3',
isActive: true
}
]
}
},
computed: {
activeUsers() {
return this.users.filter(function (user) {
return user.isActive;
})
}
}
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/demo
示例2:有公共的状态
公共代码
路由(router/index.js)
import Vue from 'vue'
import Router from 'vue-router'
import Demo from "../views/Demo";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/demo',
name: 'Demo',
component: Demo,
}
],
})
反例
代码
Demo.vue
<template>
<div class="hello">
<ul>
<li
v-for="user in users"
v-if="userActive"
:key="user.userId"
>
{{user.userName}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Demo',
data () {
return {
userActive: true,
users: [
{
userId: 1,
userName: 'Tony1',
},
{
userId: 2,
userName: 'Tony2',
},
{
userId: 3,
userName: 'Tony3',
}
]
}
},
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/demo
好例子
代码
Demo.vue
<template>
<div class="hello">
<ul v-if="userActive">
<li
v-for="user in users"
:key="user.userId"
>
{{user.userName}}
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Demo',
data () {
return {
userActive: true,
users: [
{
userId: 1,
userName: 'Tony1',
},
{
userId: 2,
userName: 'Tony2',
},
{
userId: 3,
userName: 'Tony3',
}
]
}
},
}
</script>
<style scoped>
</style>
测试
访问:http://localhost:8080/#/demo