v-if和v-for同时使用问题
在vue2的官方文档中提到了不推荐v-if和v-for同时使用,给出的解释是在两者中,v-for具有比v-if更高的优先级(vue2)。
实例
html
<ul>
<li
v-for="user in users"
v-if="user.isActive"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
当 Vue 处理指令时,v-for
比 v-if
具有更高的优先级,因此上面的代码将会经过如下运算:
js
this.users.map(function (user) {
if (user.isActive) {
return user.name
}
})
不推荐使用原因
如果v-for
和 v-if
同时使用, 会导致页面可能只要渲染一小部分用户的元素,但也会在每次重新渲染的时候遍历整个列表的情况。如果有1000个元素,但只有1个元素符合v-if
的条件,最终只会渲染这个符合条件的元素,那么就浪费了999个v-if
的计算。
替代方法
方法一
以上一个例子为例,将其更换为在一个计算属性上遍历:
html
<ul>
<li
v-for="user in activeUsers"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
js
computed: {
activeUsers: function () {
return this.users.filter(function (user) {
return user.isActive
})
}
}
适用场景
该方法在计算属性中将列表过滤,在v-for
中直接使用过滤后的列表,更倾向于使用在当需要对数据进行复杂的处理或计算的情况,使用计算属性可以方便地将处理逻辑封装起来,使模板更加清晰简洁,并且计算属性在处理数据的同时能够提高页面性能。
优点
- 过滤后的列表只会在
users
数组发生相关变化时才被重新运算,过滤更高效。 - 使用
v-for="user in activeUsers"
之后,我们在渲染的时候只遍历符合条件的元素,渲染更高效。 - 将渲染页面的逻辑和业务逻辑分离开来,使它们彼此独立,可维护性 (对逻辑的更改和扩展) 更强。
缺点
- 对于较大的数组,计算属性可能会影响性能。因为每当计算属性被访问时,都会重新遍历整个
users
数组。
方法二
通过将 v-if
移动到容器元素ul上,不会对列表中的每个元素检查是否符合v-if
的条件,只需要检查容器元素是否符合展示条件,且不会在条件为否的时候运算 v-for
。如果没有容器元素,则可以在外层嵌套template
,在这层进行v-if
的判断。
html
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
/>
{{ user.name }}
</li>
</ul>
适用场景
该方法避免了渲染本应该被隐藏的列表。如果需要根据某个条件动态渲染一组元素时,可以使用v-if
指令。
优点
- 使用
v-if
指令可以更加灵活地控制元素的显示和隐藏,可以根据需要动态地添加或删除DOM元素。 - 在容器元素上使用
v-if
可以提高页面性能,因为只有在shouldShowUsers
为true
时才会渲染列表,而不是在每个列表项上都进行判断。
缺点
- 在模板中嵌套过多的指令可能会使代码变得难以理解和维护。
总结
- 在vue2中,不要把
v-if
和v-for
同时用在同一个元素上,会带来性能上的浪费,即每次渲染都会先循环再进行条件的判断。 - 替代方法一,可通过计算属性
computed
提前过滤掉那些不需要显示的项来实现最终效果。 - 替代方法二,可通过在外层添加
v-if
判断,内部进行v-for
循环的方法来实现最终效果。