跳到主要内容

Vue 条件渲染

条件渲染根据表达式的值决定是否渲染元素。Vue 提供了 v-ifv-elsev-else-ifv-show 指令来实现条件渲染。

v-if 指令

v-if 指令根据表达式的值决定是否渲染元素:

<h1 v-if="isShow">这是一个标题</h1>
<script setup>
import { ref } from 'vue'
const isShow = ref(true)
</script>

isShowtrue 时,元素会被渲染;为 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-showv-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-ifv-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 条件渲染的相关内容:

  1. v-if:条件为 true 时渲染元素,为 false 时不渲染
  2. v-else:配合 v-if 使用,表示 else 分支
  3. v-else-if:多条件判断
  4. v-show:条件为 false 时通过 CSS 隐藏元素
  5. v-if vs v-show:选择合适的方式根据使用场景
  6. key 属性:控制元素是否复用

练习

  1. 创建一个用户登录状态切换的示例
  2. 实现一个简单的标签页组件
  3. 比较 v-if 和 v-show 的性能差异

准备好进入下一章,学习列表渲染的内容了吗?