Vue3 零基础每日笔记(015):条件渲染 v-if 与 v-show——控制 DOM 生死还是控制显隐

一、前言

进入模板与指令篇。第一个需求特别常见:登录了显示用户中心,没登录显示登录按钮;这个面板要显示,那个不要。Vue 提供两个指令干这事:v-if 和 v-show。功能看着一样,底层完全不同,它们的区别是高频面试题,今天一次讲透。

二、v-if:真·增删 DOM

v-if="表达式":表达式为真,元素渲染;为假,元素从 DOM 里彻底消失

vue 复制代码
<template>
  <p v-if="isLogin">欢迎回来,尊贵的用户</p>
  <button @click="isLogin = !isLogin">切换登录状态</button>
</template>

<script setup>
import { ref } from 'vue'

const isLogin = ref(false)
</script>

没登录时按 F12 看一下:那个 <p> 标签根本不存在。v-if 是"不满足就不造出来",切来切去就是真实地创建、销毁元素。

三、v-else-if 与 v-else:多分支链

和 JS 的 if/else if/else 一样,可以串成一串:

vue 复制代码
<template>
  <p v-if="score >= 90">优秀 🏆</p>
  <p v-else-if="score >= 60">及格 💪</p>
  <p v-else>不及格,重修吧 📚</p>
</template>

<script setup>
import { ref } from 'vue'
const score = ref(75)
</script>

铁律:v-else-if / v-else 必须紧跟在 v-if(或上一个 v-else-if)元素的后面,中间插了别的元素就断链报错。

四、v-show:假的隐藏,真的"css 隐身术"

v-show 效果一样,但机制完全不同------元素永远在 DOM 里 ,只是切换 CSS 的 display

vue 复制代码
<template>
  <p v-show="isVip">VIP 专享内容</p>
</template>

v-show 为 false 时按 F12:标签还在,只是多了 style="display: none;"

五、核心区别对比(面试高频)

对比项 v-if v-show
本质 真实创建 / 销毁 DOM 一直渲染,切换 display
初始渲染 条件为 false 时不渲染(惰性) 无论真假都渲染
切换开销 大(创建/销毁) 小(只改 CSS)
初始开销 小(不显示就不渲染) 大(永远渲染)
支持 template 包裹
配 v-else 链

选型口诀一句话:切换频繁用 v-show,条件很少变用 v-if。

场景对号入座:

  • 登录/未登录的大区块、权限模块 → v-if(几乎不切换,false 时还能省渲染)
  • Tab 页签、弹窗这类高频开关 → v-show(来回切换不重新创建)

六、v-if 的一个隐藏福利:组件生命周期

v-if 切走时,里面的组件会被真正销毁(触发 onUnmounted),切回来重新创建(重新触发 onMounted)。这个特性可以用来"重置"一个组件的状态。配合 keep-alive 缓存组件是 030 篇的主题,这里先知道行为差异。

七、综合实战:权限提示 + Tab 切换

两个指令各干最适合的活:

vue 复制代码
<template>
  <!-- v-if:登录态大区块,几乎不变 -->
  <div v-if="isLogin" class="panel">
    <p>👤 {{ username }},欢迎回来</p>

    <!-- v-show:tab 高频切换 -->
    <div class="tabs">
      <button @click="activeTab = 'post'">我的帖子</button>
      <button @click="activeTab = 'star'">我的收藏</button>
    </div>
    <div v-show="activeTab === 'post'">📝 帖子列表内容</div>
    <div v-show="activeTab === 'star'">⭐ 收藏列表内容</div>
  </div>

  <p v-else>请先登录后查看 <button @click="isLogin = true">去登录</button></p>
</template>

<script setup>
import { ref } from 'vue'

const isLogin = ref(false)
const username = ref('小明')
const activeTab = ref('post')
</script>

品味分工:登录区块用 v-if(低频切换 + 严格互斥,配了 v-else);Tab 内容用 v-show(高频来回切,不销毁重建)。

【截图位置:未登录提示、登录后 Tab 切换的运行效果】

八、踩坑记录

  1. v-if 和 v-for 写在同一元素 :Vue3 里 v-if 优先级更高,此时访问不到 v-for 的 item,直接报错。正确做法:用 computed 先过滤数组,或外层包 template 写 v-for
  2. v-show 想配合 template:不行,template 不是真实 DOM 没法挂 display,只能用 v-if
  3. v-else 断链:中间插了别的元素,报"v-else 没有相邻的 v-if"
  4. v-if 里放昂贵组件:条件为 false 时确实不渲染(这是优点),但每次切换都完整销毁重建,高频操作的场景误用 v-if 会明显卡顿
  5. 初始不显示的弹窗用了 v-show:弹窗内所有内容(哪怕从不打开)都会被初始渲染,白白多花时间;低频弹窗建议 v-if

九、今日小结

  • v-if:真实增删 DOM,惰性渲染,支持 v-else 链和 template
  • v-show:CSS 显隐,永远渲染,切换零成本
  • 口诀:频繁切换 v-show,少变条件 v-if
  • v-if 会销毁/重建内部组件,可用来重置状态

作者:陈志宝

下篇预告

页面批量展示数据离不开列表:任务清单、商品列表、表格行。下一篇 v-for 列表渲染------顺便讲透那个经典面试题:key 到底是干嘛的?为什么不能用 index 当 key?

相关推荐
掘金者阿豪1 小时前
OceanBase 和金仓怎么选?别只看分布式,复杂查询更考验架构取舍
前端·后端·架构
Bug修理工Bubble1 小时前
Swift ARC:一个对象到底什么时候才会被释放?
前端
ClouGence1 小时前
GPT-6 做 UI 自动化测试:Demo 惊艳,但真的适合长期回归吗?
前端·chatgpt·测试
阿酷tony2 小时前
视频专栏列表的防录屏水印和跑马灯效果(也可网站调用)
java·前端·音视频
Bs_MoneyMagnet2 小时前
基于springboot+vue的宠物殡葬管理平台的设计与实现 源码+文档
java·javascript·vue.js·spring boot·后端·宠物
凌风的跨境分享2 小时前
Temu店群运维提效:定时策略自动化任务全场景实操指南
大数据·运维·前端·人工智能·架构·自动化
linux_cfan2 小时前
videojs v10 源代码系列解读:06 · DOM 工具箱:事件、聚焦、Shadow DOM、定位
前端
尾善爱看海2 小时前
Vue 面试进阶篇:Composition API、插槽、自定义指令……8 个章节 + 高频面试题全解析
前端·javascript·vue.js·面试·vue
SEO_juper3 小时前
外贸多语言站最隐蔽的流量杀手:hreflang 错了,谷歌把德语页推给美国人(附审计脚本)
开发语言·前端·python·seo·独立站·谷歌优化