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循环的方法来实现最终效果。