标准答案
- 不建议把 v-for 和 v-if 写在同一个元素上,因为这样会让列表遍历和条件过滤耦合在模板里,可读性和性能都不好。
- Vue 2 中同一元素上 v-for 优先级高于 v-if,所以 v-if 可以访问 v-for 当前项。
- Vue 3 中 v-if 优先级高于 v-for,同一元素上 v-if 不能直接访问 v-for 的局部变量,迁移时可能报错。
- 如果是过滤列表,优先用 computed 先得到 filteredList,再用 v-for 渲染。
- 如果是控制整段列表是否显示,把 v-if 放到外层 template 或容器上;如果是控制单项内部内容,把条件放到子元素上。
题目解析
这题要答出两个层面:为什么不建议同写,以及 Vue 2 / Vue 3 优先级变化。
computed 过滤能让模板保持清楚,也能避免每一轮渲染都在模板里混合判断。
外层 v-if 和列表项内部 v-if 是不同需求。前者控制整组显示,后者控制每个项的局部区域。
代码示例
把过滤放到 computed 里,模板只负责渲染过滤后的列表。
Vue
<script setup lang="ts">
import { computed } from 'vue'
const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false }
]
const activeUsers = computed(() => {
return users.filter(user => user.active)
})
</script>
<template>
<ul v-if="activeUsers.length">
<li v-for="user in activeUsers" :key="user.id">
{{ user.name }}
</li>
</ul>
</template>常见误区
- Vue 3 中仍然认为 v-for 优先级高于 v-if,在 v-if 里直接访问当前项。
- 用 v-if 在模板里过滤列表,导致模板逻辑变复杂。
- 为了避免警告随便包一层 div,破坏列表语义或样式结构。