目录
- 一、核心区别速览
- 二、图解区别
- v-if:真正的条件渲染
- [v-show:CSS 切换](#v-show:CSS 切换)
- 三、代码演示
- [v-if 示例](#v-if 示例)
- [v-show 示例](#v-show 示例)
- 四、性能对比详解
- 五、实际场景选择
- [场景1:频繁切换 → 用 v-show](#场景1:频繁切换 → 用 v-show)
- [场景2:很少切换 → 用 v-if](#场景2:很少切换 → 用 v-if)
- [场景3:初始可能不显示 → 用 v-if](#场景3:初始可能不显示 → 用 v-if)
- 六、优先级说明
- 七、源码层面的区别
- [v-if 的编译结果](#v-if 的编译结果)
- [v-show 的编译结果](#v-show 的编译结果)
- 八、面试高频问题
- [Q1:v-if 和 v-show 的区别?](#Q1:v-if 和 v-show 的区别?)
- [Q2:什么时候用 v-if,什么时候用 v-show?](#Q2:什么时候用 v-if,什么时候用 v-show?)
- [Q3:v-if 和 v-show 能一起用吗?](#Q3:v-if 和 v-show 能一起用吗?)
一、核心区别速览
| 对比维度 | v-if | v-show |
|---|---|---|
| 控制方式 | 真正的条件渲染 | CSS 切换 display: none |
| DOM 存在性 | 条件为假时 DOM 不存在 | DOM 始终存在 |
| 初始渲染 | 条件为假时不渲染 | 条件为假时渲染但隐藏 |
| 切换开销 | 高(销毁/重建 DOM) | 低(只切换 CSS) |
| 初始开销 | 低(条件假时不渲染) | 高(总是渲染) |
支持 template |
✅ 支持 | ❌ 不支持 |
支持 v-else |
✅ 支持 | ❌ 不支持 |
| 适用场景 | 很少切换 | 频繁切换 |
二、图解区别
v-if:真正的条件渲染
条件 = true 条件 = false
┌─────────────┐ ┌─────────────┐
│ │ │ │
│ DOM 存在 │ │ DOM 不存在 │
│ 显示内容 │ │ (被移除) │
│ │ │ │
└─────────────┘ └─────────────┘
条件 false → true:创建 DOM
条件 true → false:销毁 DOM
v-show:CSS 切换
条件 = true 条件 = false
┌─────────────┐ ┌─────────────┐
│ │ │ display: │
│ DOM 存在 │ │ none │
│ 显示内容 │ │ (隐藏但存在)│
│ │ │ │
└─────────────┘ └─────────────┘
条件 false → true:display: none → display: 原值
条件 true → false:display: 原值 → display: none
DOM 始终存在,只是隐藏/显示
三、代码演示
v-if 示例
javascript
<template>
<div>
<!-- 条件为 true 时才渲染 -->
<div v-if="isVisible">
<p>这个元素只在 isVisible = true 时才存在</p>
</div>
<!-- ✅ 支持 template(批量渲染) -->
<template v-if="isLoggedIn">
<h2>欢迎回来</h2>
<p>用户名:{{ username }}</p>
</template>
<!-- ✅ 支持 v-else-if 和 v-else -->
<div v-if="status === 'success'">成功</div>
<div v-else-if="status === 'loading'">加载中</div>
<div v-else>失败</div>
</div>
</template>
v-show 示例
javascript
<template>
<div>
<!-- 条件为 false 时,display: none,但 DOM 还在 -->
<div v-show="isVisible">
<p>这个元素始终存在,只是通过 CSS 隐藏/显示</p>
</div>
<!-- ❌ v-show 不支持 template -->
<template v-show="isLoggedIn"> <!-- 无效! -->
<h2>欢迎回来</h2>
</template>
<!-- ❌ v-show 不支持 v-else -->
<div v-show="status === 'success'">成功</div>
<div v-else>失败</div> <!-- 不生效! -->
</div>
</template>
四、性能对比详解
| 场景 | v-if | v-show |
|---|---|---|
| 初始渲染(条件为假) | ✅ 不渲染,快 | ❌ 渲染但隐藏,慢 |
| 切换(假→真) | ❌ 创建 DOM,慢 | ✅ 改 display,快 |
| 切换(真→假) | ❌ 销毁 DOM,慢 | ✅ 改 display,快 |
| 频繁切换 | ❌ 不推荐 | ✅ 推荐 |
| 很少切换 | ✅ 推荐 | ⚠️ 初始开销大 |
五、实际场景选择
场景1:频繁切换 → 用 v-show
javascript
<template>
<!-- 选项卡/标签页频繁切换 -->
<div class="tabs">
<button @click="activeTab = 'tab1'">标签1</button>
<button @click="activeTab = 'tab2'">标签2</button>
<!-- 频繁切换,用 v-show -->
<div v-show="activeTab === 'tab1'">内容1</div>
<div v-show="activeTab === 'tab2'">内容2</div>
</div>
</template>
场景2:很少切换 → 用 v-if
javascript
<template>
<!-- 用户登录状态(切换很少) -->
<div v-if="isLoggedIn">
<UserDashboard />
</div>
<div v-else>
<LoginPage />
</div>
<!-- 权限控制(页面加载时决定,基本不变) -->
<AdminPanel v-if="user.isAdmin" />
</template>
场景3:初始可能不显示 → 用 v-if
javascript
<template>
<!-- 弹窗:初始不显示,用 v-if 避免渲染 -->
<Modal v-if="showModal" @close="showModal = false" />
<!-- 懒加载组件 -->
<LazyComponent v-if="shouldLoad" />
</template>
六、优先级说明
v-if 的优先级远高于 v-show:
javascript
<template>
<!-- ⚠️ 注意:v-if 优先级高于 v-for -->
<!-- ❌ 不推荐:v-if 和 v-for 一起用 -->
<div v-for="item in list" v-if="item.active" :key="item.id">
{{ item.name }}
</div>
<!-- ✅ 推荐:用 computed 过滤 -->
<div v-for="item in activeList" :key="item.id">
{{ item.name }}
</div>
</template>
优先级顺序:
v-if > v-for > v-show
v-if和v-show不在同一执行阶段,v-if的条件判断更早执行。
七、源码层面的区别
v-if 的编译结果
javascript
// 源码:v-if 会被编译成三元表达式
// <div v-if="show">内容</div>
// 编译后(简化)
show ? renderDiv() : null
v-show 的编译结果
javascript
// 源码:v-show 会被编译成样式绑定
// <div v-show="show">内容</div>
// 编译后(简化)
<div style={show ? null : { display: 'none' }}>内容</div>
八、面试高频问题
Q1:v-if 和 v-show 的区别?
答:
控制方式不同 :v-if 是真正的条件渲染,条件为假时 DOM 不存在;v-show 只是切换 CSS 的
display: none,DOM 始终存在性能开销不同:v-if 切换开销高(创建/销毁 DOM),初始开销低;v-show 切换开销低,初始开销高
功能支持不同 :v-if 支持
template和v-else,v-show 不支持
Q2:什么时候用 v-if,什么时候用 v-show?
答:
频繁切换 → 用
v-show,切换成本低很少切换 → 用
v-if,减少初始渲染开销初始可能不显示 → 用
v-if,避免渲染无用 DOM需要配合 v-else → 只能用
v-if
Q3:v-if 和 v-show 能一起用吗?
答:
可以,但没必要。因为 v-if 优先级更高,如果 v-if 条件为假,v-show 根本不会生效(DOM 都不存在)。通常只需要用一个。
v-if 是"真实的"条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建
v-show 是简单的 CSS 切换,适合频繁切换的场景
v-if 也是懒加载的,初始条件为假时,什么也不做,直到条件第一次变为真时才开始渲染
v-if 优先级高于 v-for,不建议一起使用