WinlatorXR
881.97M · 2026-02-04
在 Vue 模板开发中,指令的优先级和渲染机制直接决定了应用的性能。尤其是 v-if 与 v-for 的“爱恨情仇”,在 Vue 2 和 Vue 3 中经历了完全相反的变革。本文将带你从底层逻辑出发,看透这些指令的本质。
在 Vue 2 中,v-for 的优先级高于 v-if。
这意味着如果你在同一个元素上同时使用它们,Vue 会先执行循环,再对循环出的每一个项进行条件判断。
v-if 为 false,循环依然会完整执行,造成极大的性能浪费。在 Vue 3 中,v-if 的优先级高于 v-for。
此时,如果两者并列,v-if 会先执行。但由于此时循环尚未开始,v-if 无法访问到 v-for 循环中的变量,会导致报错。
无论哪个版本,永远不要把v-if和v-for同时用在同一个元素上。如果非要一起使用可以通过如下方式:
方案 A:外层包裹 template(推荐)
如果判断条件与循环项无关,先判断再循环。
<template v-if="isShow">
<div v-for="item in items" :key="item.id">{{ item.name }}</div>
</template>
方案 B:使用计算属性 computed(推荐)
如果需要根据条件过滤列表项,先过滤再循环。
<script setup lang="ts">
import { computed } from 'vue';
const activeItems = computed(() => items.value.filter(item => item.isActive));
</script>
<template>
<div v-for="item in activeItems" :key="item.id">{{ item.name }}</div>
</template>
两者都能控制显隐,但“手段”截然不同。
| 特性 | v-if | v-show |
|---|---|---|
| 手段 | 真正的数据驱动,动态添加/删除 DOM 元素 | CSS 驱动,切换 display: none 属性 |
| 本质 | 组件的销毁与重建 | 元素的显示与隐藏 |
| 初始渲染 | 若初始为 false,则完全不渲染 | 无论真假,都会渲染并保留 DOM |
| 切换消耗 | 较高(涉及生命周期与 DOM 增删) | 较低(仅改变 CSS) |
| 生命周期 | 切换时触发完整生命周期 | 不触发生命周期钩子 |
由于 v-if 是真实的销毁与重建,它会完整走一遍生命周期。
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
// 假设这是一个被 v-if 控制的子组件
onMounted(() => {
console.log('子组件已创建并挂载 (v-if 为 true)');
});
onUnmounted(() => {
console.log('子组件已卸载并销毁 (v-if 为 false)');
});
</script>
v-if 切换:
false -> true:触发 onBeforeMount, onMounted 等。true -> false:触发 onBeforeUnmount, onUnmounted 等。v-show 切换:
v-show:如果元素在页面上频繁切换(如 Tab 标签、折叠面板),v-show 的性能表现更优。v-if:如果运行条件下改变较少,或者该部分包含大量复杂的子组件,使用 v-if 可以保证初始渲染的轻量化,并在不需要时彻底释放内存。