Skip to content
On this page

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-forv-if 具有更高的优先级,因此上面的代码将会经过如下运算:

js
this.users.map(function (user) {
 if (user.isActive) {
  return user.name
 }
})

不推荐使用原因

如果v-forv-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可以提高页面性能,因为只有在shouldShowUserstrue时才会渲染列表,而不是在每个列表项上都进行判断。

缺点

  • 在模板中嵌套过多的指令可能会使代码变得难以理解和维护。

总结

  • 在vue2中,不要把v-ifv-for 同时用在同一个元素上,会带来性能上的浪费,即每次渲染都会先循环再进行条件的判断。
  • 替代方法一,可通过计算属性computed提前过滤掉那些不需要显示的项来实现最终效果。
  • 替代方法二,可通过在外层添加v-if判断,内部进行v-for循环的方法来实现最终效果。