前言
写 Vue 时,最容易踩的小坑之一,就是给 <template>
套一个 v-show
。编辑器不报错,页面却“消失”了。很多人以为这是 bug,其实它只是 Vue 的底层设计在默默提醒:<template>
不是真节点,它只是个“草稿纸”。
一、为什么 <template>
拒绝 v-show
v-show
的本质是切换元素的 CSS:display: none
。浏览器要找到真实 DOM 节点,才能给它加样式。而 <template>
在运行时会被完全剥离,不会留下任何标签,Vue 找不到节点,也就无处下刀。
举个反面教材:
1<template v-show="false">
2 <p>我永远被渲染</p>
3</template>
打开控制台,你会看到 <p>
还是生成了,但 v-show
的指令像从没来过。
二、官方的正确姿势
- 想按条件渲染一块区域,用
v-if
:
1<template v-if="show">
2 <p>只在 show 为 true 时出现</p>
3</template>
- 想按条件展示一个真实节点,用
v-show
:
1<p v-show="show">我只是在隐藏/显示</p>
三、实战演练:弹窗小组件
需求:点击按钮,弹窗淡入淡出。
思路:弹窗需要保留 DOM(方便动画),所以外层用 div
套 v-show
,内部用 <template>
组织结构。
1<template>
2 <button @click="visible = !visible">切换弹窗</button>
3
4 <!-- 真实节点,可以 v-show -->
5 <transition name="fade">
6 <div v-show="visible" class="modal">
7 <!-- 内部用 template 纯粹排版 -->
8 <template>
9 <h3>温馨提示</h3>
10 <p>内容区域</p>
11 <button @click="visible=false">关闭</button>
12 </template>
13 </div>
14 </transition>
15</template>
16
17<style>
18.fade-enter-active, .fade-leave-active {
19 transition: opacity .3s;
20}
21.fade-enter-from, .fade-leave-to {
22 opacity: 0;
23}
24.modal {
25 position: fixed;
26 top: 50%; left: 50%;
27 transform: translate(-50%,-50%);
28 background: #fff;
29 padding: 20px;
30 box-shadow: 0 2px 10px rgba(0,0,0,.2);
31}
32</style>
四、总结
<template>
只是编译时的“占位符”,别让它承担运行时样式切换的重任;该渲染就交给 v-if
,该显隐就交给真实节点加 v-show
。
个人笔记记录 2021 ~ 2025