Vue 条件渲染
条件渲染根据表达式的值决定是否渲染元素。Vue 提供了 v-if、v-else、v-else-if 和 v-show 指令来实现条件渲染。
v-if 指令
v-if 指令根据表达式的值决定是否渲染元素:
<h1 v-if="isShow">这是一个标题</h1>
<script setup>
import { ref } from 'vue'
const isShow = ref(true)
</script>
当 isShow 为 true 时,元素会被渲染;为 false 时,元素不会被渲染(甚至不会存在于 DOM 中)。
v-else 指令
v-else 配合 v-if 使用,表示 v-if 条件不满足时渲染的内容:
<div v-if="isLoggedIn">
欢迎回来!
</div>
<div v-else>
请登录
</div>
<script setup>
import { ref } from 'vue'
const isLoggedIn = ref(false)
</script>
v-else-if 指令
v-else-if 用于多个条件的判断:
<div v-if="score >= 90">优秀</div>
<div v-else-if="score >= 80">良好</div>
<div v-else-if="score >= 60">及格</div>
<div v-else>不及格</div>
<script setup>
import { ref } from 'vue'
const score = ref(85)
</script>
v-show 指令
v-show 和 v-if 类似,但有重要区别:
v-if:条件为 false 时,元素不会渲染到 DOM 中v-show:条件为 false 时,元素会渲染到 DOM 中,只是通过 CSS 的display: none隐藏
<h1 v-show="isShow">使用 v-show</h1>
<script setup>
import { ref } from 'vue'
const isShow = ref(true)
</script>
v-if vs v-show 选择
使用 v-if 的场景
- 条件不太可能改变:避免不必要的 DOM 操作
- 需要切换复杂的组件:v-if 会完全销毁和重建组件
- 需要配合 v-else:使用 else 分支
<!-- 登录/未登录状态的切换 -->
<div v-if="isLoggedIn">
<UserProfile />
</div>
<div v-else>
<LoginForm />
</div>
使用 v-show 的场景
- 频繁切换:v-show 只改变 CSS,性能更好
- 简单的显示/隐藏:不需要复杂的条件逻辑
<!-- 弹窗的显示/隐藏 -->
<div v-show="isModalVisible" class="modal">
这是一个弹窗
</div>
条件渲染与 key
Vue 默认会尽可能复用已有的元素。如果你不想让 Vue 复用元素,可以使用 key 属性:
<template v-if="loginType === 'username'">
<label>用户名</label>
<input key="username-input" placeholder="请输入用户名" />
</template>
<template v-else>
<label>邮箱</label>
<input key="email-input" placeholder="请输入邮箱" />
</template>
添加 key 后,每次切换都会创建新的输入框,而不是复用。
在 template 上使用 v-if
如果想同时控制多个元素的条件渲染,可以使用 <template> 包装多个元素:
<template v-if="show">
<h1>标题</h1>
<p>段落1</p>
<p>段落2</p>
</template>
这样 v-if 会作用到所有 <template> 内的元素上。
条件渲染与 v-for
v-if 和 v-for 一起使用时,v-for 的优先级更高:
<!-- 不推荐,v-if 会在 v-for 之后评估 -->
<li v-for="item in items" v-if="item.show">{{ item.name }}</li>
推荐使用计算属性先过滤数据:
<script setup>
import { ref, computed } from 'vue'
const items = ref([
{ name: '苹果', show: true },
{ name: '香蕉', show: false },
{ name: '橙子', show: true }
])
const visibleItems = computed(() => {
return items.value.filter(item => item.show)
})
</script>
<template>
<ul>
<li v-for="item in visibleItems" :key="item.name">
{{ item.name }}
</li>
</ul>
</template>
示例:显示隐藏密码
<script setup>
import { ref } from 'vue'
const showPassword = ref(false)
const password = ref('123456')
</script>
<template>
<div class="input-group">
<input
:type="showPassword ? 'text' : 'password'"
v-model="password"
/>
<button @click="showPassword = !showPassword">
{{ showPassword ? '隐藏' : '显示' }}
</button>
</div>
</template>
<style scoped>
.input-group {
display: flex;
gap: 10px;
}
input {
padding: 8px;
}
button {
padding: 8px 16px;
}
</style>
示例:标签页切换
<script setup>
import { ref } from 'vue'
const activeTab = ref('home')
const tabs = [
{ id: 'home', label: '首页', content: '这是首页内容' },
{ id: 'about', label: '关于', content: '这是关于页面' },
{ id: 'contact', label: '联系', content: '这是联系方式' }
]
</script>
<template>
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab.id"
:class="{ active: activeTab === tab.id }"
@click="activeTab = tab.id"
>
{{ tab.label }}
</button>
<div class="tab-content">
<div v-if="activeTab === 'home'">{{ tabs[0].content }}</div>
<div v-else-if="activeTab === 'about'">{{ tabs[1].content }}</div>
<div v-else-if="activeTab === 'contact'">{{ tabs[2].content }}</div>
</div>
</div>
</template>
<style scoped>
.tabs {
max-width: 400px;
}
button {
margin-right: 5px;
padding: 8px 16px;
}
button.active {
background-color: #42b883;
color: white;
}
.tab-content {
margin-top: 20px;
padding: 20px;
border: 1px solid #ddd;
}
</style>
小结
本章我们学习了 Vue 条件渲染的相关内容:
- v-if:条件为 true 时渲染元素,为 false 时不渲染
- v-else:配合 v-if 使用,表示 else 分支
- v-else-if:多条件判断
- v-show:条件为 false 时通过 CSS 隐藏元素
- v-if vs v-show:选择合适的方式根据使用场景
- key 属性:控制元素是否复用
练习
- 创建一个用户登录状态切换的示例
- 实现一个简单的标签页组件
- 比较 v-if 和 v-show 的性能差异
准备好进入下一章,学习列表渲染的内容了吗?