条件渲染是Vue.js中用于根据条件显示或隐藏元素的重要特性。通过条件渲染,我们可以创建动态的用户界面,根据应用状态的不同显示不同的内容。
Vue提供了多种条件渲染指令,包括v-if、v-else、v-else-if和v-show。理解这些指令的区别和适用场景,对于编写高效、可维护的Vue应用至关重要。
在Web应用中,经常需要根据不同的条件显示不同的内容。例如:
根据用户是否登录显示不同的界面,未登录用户显示登录表单,已登录用户显示用户面板。
数据加载时显示加载指示器,加载完成显示内容,加载失败显示错误信息。
根据用户权限显示或隐藏特定的功能按钮或菜单项。
多步骤表单中,根据当前步骤显示相应的表单字段。
v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值(truthy)时被渲染。
<!-- 如果isShow为true,则渲染div -->
<div v-if="isShow">这个元素会被渲染</div>
<!-- 使用表达式 -->
<div v-if="count > 0">计数大于0</div>
<!-- 使用计算属性 -->
<div v-if="isActive">活跃状态</div>
DOM检查提示: 使用浏览器开发者工具检查元素,观察元素是否在DOM中。
<template>元素上使用v-else和v-else-if配合使用可以使用v-else和v-else-if指令来表示v-if的"else 块"和"else-if 块"。
<!-- v-if 和 v-else -->
<div v-if="isActive">活跃状态</div>
<div v-else>非活跃状态</div>
<!-- v-if、v-else-if 和 v-else -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>不是A/B/C</div>
v-else和v-else-if必须紧跟在v-if或v-else-if元素之后v-else块(如果存在)v-else-if可以避免复杂的嵌套条件v-show指令根据条件展示元素,与v-if不同,v-show始终会渲染元素,只是通过CSS的display属性切换显示/隐藏。
<!-- 如果isShow为true,则显示div -->
<div v-show="isShow">这个元素会被显示或隐藏</div>
<!-- 使用表达式 -->
<div v-show="count > 0">计数大于0时显示</div>
DOM检查提示: 使用浏览器开发者工具检查元素,无论条件如何,元素始终在DOM中,只是通过CSS控制显示/隐藏。
性能观察:
v-show性能更好| 特性 | v-if | v-show |
|---|---|---|
| 渲染方式 | 条件性地渲染元素,条件为假时元素不会被渲染到DOM中 | 始终渲染元素,只是通过CSS的display属性切换显示/隐藏 |
| 初始渲染开销 | 较低(如果初始条件为假,则不会渲染) | 较高(无论初始条件如何,都会渲染) |
| 切换开销 | 较高(需要销毁和重建元素) | 较低(只是切换CSS属性) |
| 使用场景 |
|
|
| 生命周期 | 条件变化时会触发组件的创建/销毁生命周期钩子 | 条件变化时不会触发生命周期钩子,元素始终存在 |
| 与v-else配合 | 支持 | 不支持 |
| 与<template>配合 | 支持 | 不支持 |
| 性能影响 | 切换时性能开销大,但初始渲染可能更快 | 切换时性能开销小,但初始渲染可能更慢 |
| 示例 |
|
|
// 适合使用 v-if 的场景:
// 1. 用户登录状态(不经常变化)
<div v-if="isLoggedIn">
<user-panel></user-panel>
</div>
<div v-else>
<login-form></login-form>
</div>
// 2. 权限控制(页面加载时确定)
<button v-if="user.role === 'admin'">
删除
</button>
// 3. 需要懒加载的内容
<div v-if="loadData">
<heavy-component></heavy-component>
</div>
// 适合使用 v-show 的场景:
// 1. 频繁切换的UI元素
<div v-show="isMenuOpen">
<navigation-menu></navigation-menu>
</div>
// 2. 标签页切换
<div v-show="activeTab === 'profile'">
个人资料
</div>
<div v-show="activeTab === 'settings'">
设置
</div>
// 3. 加载状态
<div v-show="isLoading">
<loading-spinner></loading-spinner>
</div>
// 两者结合使用
<div v-if="hasData">
<!-- 有数据时才渲染数据容器 -->
<div v-show="!isLoading">
<!-- 数据加载完成时才显示 -->
{{ data }}
</div>
<div v-show="isLoading">
加载中...
</div>
</div>
<div v-else>
暂无数据
</div>
如果需要切换多个元素,可以使用<template>元素作为包裹元素,并在其上使用条件指令。<template>本身不会被渲染到DOM中。
渲染结果:
注:这里有一个额外的div包裹元素
注:没有额外的包裹元素,DOM结构更简洁
<!-- 不使用 template -->
<div v-if="condition">
<div>元素 A</div>
<div>元素 B</div>
<div>元素 C</div>
</div>
<div v-else>
<div>其他元素</div>
</div>
<!-- 使用 template -->
<template v-if="condition">
<div>元素 A</div>
<div>元素 B</div>
<div>元素 C</div>
</template>
<template v-else>
<div>其他元素</div>
</template>
<template>元素不会出现在最终的DOM中<template>上使用条件指令v-show不能在<template>上使用v-for渲染多个元素Vue会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这可能会带来一些问题,特别是在表单元素中。使用key属性可以强制元素不复用。
切换登录方式,观察输入框状态是否保留:
输入内容后切换登录方式,内容会被保留
输入内容后切换登录方式,内容会被保留
输入内容后切换登录方式,内容会被清空
输入内容后切换登录方式,内容会被清空
<!-- 不使用 key -->
<template v-if="loginType === 'username'">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名">
</template>
<template v-else>
<label>邮箱:</label>
<input type="email" placeholder="请输入邮箱">
</template>
<!-- 使用 key -->
<template v-if="loginType === 'username'">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" key="username-input">
</template>
<template v-else>
<label>邮箱:</label>
<input type="email" placeholder="请输入邮箱" key="email-input">
</template>
下面的演示展示了条件渲染的多种实际应用场景,包括用户界面切换、权限控制、表单验证等。
请先登录以访问更多功能
角色: {{ user.role }}
状态: 活跃 冻结
邮箱: 已验证 未验证
无操作权限
// 模板中的条件渲染示例
<!-- 登录状态判断 -->
<div v-if="!user.isLoggedIn">
<!-- 未登录界面 -->
<button @click="user.isLoggedIn = true">登录</button>
</div>
<!-- 已登录界面 -->
<template v-if="user.isLoggedIn">
<!-- 账户状态 -->
<div v-if="!user.isActive" class="alert alert-danger">
账户已被冻结
</div>
<!-- 权限控制 -->
<button v-if="user.role === 'admin'">
用户管理
</button>
<button v-else-if="user.role === 'editor'">
编辑文章
</button>
<button v-else>
发表评论
</button>
<!-- 持续显示的管理员提示 -->
<div v-show="user.role === 'admin'">
管理员提示信息
</div>
</template>
// 计算属性简化条件
computed: {
canComment() {
return this.user.role === 'user' ||
this.user.role === 'editor' ||
this.user.role === 'admin';
},
canEditArticles() {
return this.user.role === 'editor' ||
this.user.role === 'admin';
},
canManageUsers() {
return this.user.role === 'admin';
},
isAccountFullyActive() {
return this.user.isActive && this.user.emailVerified;
}
}
v-if的"else 块",必须紧跟在v-if或v-else-if之后v-if的"else if 块",可以多次使用display属性切换显示/隐藏,元素始终在DOM中v-if适合条件不经常变化的场景,v-show适合频繁切换的场景现在你已经掌握了条件渲染,接下来我们将学习Vue的列表渲染,包括v-for指令的使用,如何遍历数组和对象,以及列表渲染的性能优化。