在Vue开发中,页面交互往往需要根据不同的状态展示不同的内容——比如用户登录后显示个人中心,未登录时显示登录按钮;表单验证失败时显示错误提示,成功时显示提交成功信息。这种“按需显示”的需求,Vue提供了一套简洁高效的条件渲染方案,核心就是v-if、v-else、v-else-if和v-show这几个指令。今天就从基础用法到进阶技巧,全方位拆解Vue条件渲染,帮你精准掌握不同场景下的最优使用方式,写出更灵活、可维护的前端代码。
核心指令:v-if 系列——“按需渲染”的核心
v-if 是Vue中最基础、最常用的条件渲染指令,它的核心作用是:根据绑定表达式的真假,决定是否渲染当前元素及它的子元素。当表达式为真值(Truthy)时,元素会被渲染到DOM中;当表达式为假值(Falsy)时,元素会被从DOM中移除,而非简单隐藏。
1. v-if 基础用法:单个条件判断
v-if 可以直接绑定一个响应式状态,实现简单的“显示/隐藏”切换。需要注意的是,v-if 是一个指令,必须依附于某个具体的DOM元素,不能单独使用。
实战示例:根据用户登录状态显示不同内容
<script setup>
import { ref } from 'vue';
// 模拟用户登录状态:true为已登录,false为未登录
const isLogin = ref(false);
// 模拟登录操作
function login() {
isLogin.value = true;
}
// 模拟退出登录操作
function logout() {
isLogin.value = false;
}
</script>
<template>
<div class="user-section">
<!-- 已登录时显示个人中心入口 -->
<button v-if="isLogin" @click="logout">退出登录</button>
<span v-if="isLogin" class="user-info">欢迎回来,用户123</span>
<!-- 未登录时显示登录按钮 -->
<button v-if="!isLogin" @click="login">立即登录</button>
</div>
</template>
<style>
.user-section {
margin: 20px 0;
padding: 15px;
border: 1px solid #eee;
}
.user-info {
margin: 0 10px;
color: #42b983;
}
button {
padding: 6px 12px;
cursor: pointer;
border: none;
border-radius: 4px;
background: #42b983;
color: white;
}
button:hover {
opacity: 0.9;
}
</style>
2. v-else:补充v-if的“否则”场景
当v-if的条件不成立时,我们可以用v-else指令添加一个“否则”的渲染区块。需要特别注意的是,v-else 必须紧跟在v-if 或 v-else-if 元素之后,不能单独存在,也不能插入其他元素,否则Vue会无法识别。
实战示例:优化登录状态显示(用v-else简化代码)
<script setup>
import { ref } from 'vue';
const isLogin = ref(false);
function toggleLogin() {
isLogin.value = !isLogin.value;
}
</script>
<template>
<div class="user-section">
<button @click="toggleLogin">{{ isLogin ? '退出登录' : '立即登录' }}</button>
<!-- v-if 和 v-else 紧跟,实现互斥显示 -->
<div v-if="isLogin" class="user-info">
欢迎回来,用户123<br/>
<a href="#">进入个人中心</a>
</div>
<div v-else class="login-tip">
请登录后查看更多内容 😊
</div>
</div>
</template>
<style>
/* 样式沿用上面的基础样式,新增提示样式 */
.login-tip {
margin-top: 10px;
color: #666;
font-size: 14px;
}
</style>
3. v-else-if:多条件分支判断
当需要判断多个条件分支时,v-else-if 可以实现“if-else if-else”的逻辑,它可以连续使用多次,最终用v-else收尾(可选)。同样,v-else-if 必须紧跟在v-if 或前一个v-else-if 元素之后。
实战示例:根据用户等级显示不同权限提示
<script setup>
import { ref } from 'vue';
// 模拟用户等级:0-普通用户,1-会员,2-管理员
const userLevel = ref(1);
// 切换用户等级
function changeLevel(level) {
userLevel.value = level;
}
</script>
<template>
<div class="level-section">
<button @click="changeLevel(0)">普通用户</button>
<button @click="changeLevel(1)">会员用户</button>
<button @click="changeLevel(2)">管理员</button>
<div class="level-tip" v-if="userLevel === 0">
普通用户:可查看基础内容,解锁更多功能请升级会员
</div>
<div class="level-tip" v-else-if="userLevel === 1">
会员用户:可查看专属内容,享受优先客服服务
</div>
<div class="level-tip" v-else-if="userLevel === 2">
管理员:拥有全部操作权限,可管理所有用户数据
</div>
<div class="level-tip" v-else>
未知用户等级,请联系管理员
</div>
</div>
</template>
<style>
.level-section {
margin: 20px 0;
padding: 15px;
border: 1px solid #eee;
}
.level-tip {
margin-top: 15px;
padding: 10px;
border-radius: 4px;
}
.level-tip:nth-child(2) { background: #f5fafe; color: #4299e1; }
.level-tip:nth-child(3) { background: #fdf2f8; color: #9f7aea; }
.level-tip:nth-child(4) { background: #eaf6fa; color: #38b2ac; }
.level-tip:nth-child(5) { background: #faf0f5; color: #e53e3e; }
</style>
4. template 上的v-if:批量切换多个元素
v-if 必须依附于单个DOM元素,但如果我们需要同时切换多个元素的显示/隐藏,又不想额外添加一个包裹容器(比如div),就可以在template标签上使用v-if。template只是一个不可见的包装器,最终渲染的结果不会包含这个标签,完美解决“多元素切换”的需求。
实战示例:批量切换表单提示信息
<script setup>
import { ref } from 'vue';
// 模拟表单提交状态:true为提交成功,false为未提交
const submitSuccess = ref(false);
function submitForm() {
// 模拟表单提交逻辑
setTimeout(() => {
submitSuccess.value = true;
}, 1000);
}
</script>
<template>
<form class="form" @submit.prevent="submitForm">
<input type="text" placeholder="请输入内容" required />
<button type="submit">提交</button>
<!-- 用template包裹多个元素,批量切换显示/隐藏 -->
<template v-if="submitSuccess">
<div class="success-icon">✅</div>
<p class="success-tip">表单提交成功!感谢您的反馈</p>
<button type="button" @click="submitSuccess = false">重新提交</button>
</template>
</form>
</template>
<style>
.form {
margin: 20px 0;
padding: 15px;
border: 1px solid #eee;
display: flex;
flex-direction: column;
gap: 10px;
}
input {
padding: 8px;
}
.success-icon {
font-size: 24px;
color: #48bb78;
}
.success-tip {
color: #48bb78;
margin: 5px 0;
}
</style>
另一种选择:v-show 指令——“简单隐藏”的高效方案
除了v-if,Vue还提供了v-show指令用于条件显示元素,它的用法和v-if非常相似,都是通过绑定表达式的真假来控制元素的显示状态,但二者的底层实现和使用场景有很大区别。
v-show 的核心特点:无论条件是否成立,元素都会被渲染到DOM中,它只是通过切换元素的CSS display属性来控制显示/隐藏(display: none 或 display: 初始值),元素本身始终存在于DOM中。
v-show 基础用法
v-show 直接绑定响应式状态,语法和v-if一致,适合简单的显示/隐藏切换场景。
<script setup>
import { ref } from 'vue';
// 模拟开关状态
const isShow = ref(true);
function toggleShow() {
isShow.value = !isShow.value;
}
</script>
<template>
<div class="show-section">
<button @click="toggleShow">{{ isShow ? '隐藏' : '显示' }}内容</button>
<div v-show="isShow" class="show-content">
这是v-show控制的内容,隐藏时只是display: none,不会从DOM中移除
</div>
</div>
</template>
<style>
.show-section {
margin: 20px 0;
padding: 15px;
border: 1px solid #eee;
}
.show-content {
margin-top: 10px;
padding: 10px;
background: #f5f5f5;
}
</style>
注意:v-show 不支持在template标签上使用,也不能和v-else搭配使用,只能单独作用于单个DOM元素。
关键对比:v-if vs v-show 怎么选?
很多初学者会混淆v-if和v-show的用法,其实二者的核心区别在于“是否从DOM中移除元素”,这也决定了它们的适用场景。下面通过表格清晰对比,帮你快速判断:
| 对比维度 | v-if | v-show |
|---|---|---|
| DOM存在性 | 条件为假时,元素从DOM中移除 | 无论条件真假,元素始终在DOM中 |
| 实现方式 | 动态创建/销毁DOM元素 | 切换CSS display属性 |
| 初始渲染开销 | 惰性渲染:条件为假时不渲染,初始开销小 | 无论条件如何,都会渲染,初始开销大 |
| 切换开销 | 创建/销毁DOM,切换开销大 | 仅切换CSS,切换开销小 |
| 适用场景 | 条件很少切换(如登录/未登录状态) | 条件需要频繁切换(如弹窗、tab切换) |
| 支持搭配 | 支持v-else、v-else-if,支持template | 不支持v-else,不支持template |
实战建议:如果需要频繁切换显示状态(比如导航菜单、弹窗),优先用v-show;如果条件切换频率低(比如用户身份判断、页面权限控制),优先用v-if,这样能减少DOM节点数量,提升页面性能。
进阶注意:v-if 与 v-for 的使用禁忌
在实际开发中,我们可能会遇到“需要过滤列表后渲染”的场景,这时容易习惯性地将v-if和v-for写在同一个元素上,但这种用法是Vue不推荐的,因为二者的优先级不明确,会导致渲染异常和性能问题。
Vue中,当v-if和v-for同时存在于一个元素上时,v-if会先执行,也就是说,Vue会先判断每个列表项是否满足v-if的条件,再进行循环渲染,这会导致v-for的循环次数增加,影响性能。
错误示例(不推荐)
<!-- 错误:v-if和v-for写在同一个元素上 -->
<ul>
<li v-for="item in list" v-if="item.status === 1" :key="item.id">
{{ item.name }}
</li>
</ul>
正确做法(推荐)
方案1:先通过计算属性过滤列表,再用v-for渲染,避免v-if和v-for同元素
<script setup>
import { ref, computed } from 'vue';
const list = ref([
{ id: 1, name: 'Vue基础', status: 1 },
{ id: 2, name: 'React基础', status: 0 },
{ id: 3, name: 'Vue条件渲染', status: 1 },
{ id: 4, name: 'JavaScript进阶', status: 0 }
]);
// 计算属性过滤状态为1的列表项
const activeList = computed(() => {
return list.value.filter(item => item.status === 1);
});
</script>
<template>
<ul>
<!-- 只渲染过滤后的列表,无需v-if -->
<li v-for="item in activeList" :key="item.id">
{{ item.name }}
</li>
</ul>
</template>
方案2:用template包裹v-for,将v-if写在template上(适用于整体过滤列表)
<template>
<!-- 先判断列表是否有数据,再循环渲染 -->
<template v-if="list.length > 0">
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}
</li>
</ul>
</template>
<div v-else>
暂无数据
</div>
</template>
常见误区与避坑指南
- v-else、v-else-if 位置错误:必须紧跟在v-if或v-else-if元素之后,不能插入其他元素,否则会被Vue识别为无效指令;
- v-show 用于复杂组件:v-show 会始终渲染元素,即使条件为假,复杂组件的初始渲染会增加页面加载时间,建议改用v-if;
- v-if 用于频繁切换场景:频繁切换v-if会导致DOM频繁创建/销毁,产生性能开销,建议改用v-show;
- v-if 和 v-for 同元素使用:优先级混乱,导致渲染异常和性能问题,优先用计算属性过滤列表;
- 在template上使用v-show:v-show不支持template标签,会导致指令失效,需改为作用于具体DOM元素。
总结:条件渲染的最佳实践
Vue的条件渲染指令(v-if、v-else、v-else-if、v-show)为我们提供了灵活的页面交互方案,核心是根据场景选择合适的指令,兼顾性能和可读性。结合实战场景,提炼以下最佳实践:
- 简单显示/隐藏、频繁切换:用v-show,减少DOM切换开销;
- 条件切换少、需要销毁DOM:用v-if,减少初始渲染和DOM节点数量;
- 多条件分支:用v-if + v-else-if + v-else,确保指令顺序正确;
- 批量切换多个元素:用template包裹v-if,避免额外添加容器;
- 过滤列表渲染:用计算属性过滤列表后,再用v-for渲染,避免v-if和v-for同元素;
- 避免无效指令:v-show不搭配v-else、不用于template,v-else不单独使用。
掌握条件渲染的核心用法和场景差异,能让你在Vue开发中更灵活地控制页面展示,写出更高效、可维护的代码。条件渲染是Vue页面交互的基础,后续结合列表渲染、组件封装等知识点,还能实现更复杂的页面逻辑,解锁更多前端开发技巧。