【vue篇】Vue 条件渲染终极对决:v-if vs v-show 深度解析

在 Vue 开发中,v-ifv-show 都能实现"条件显示",但它们的底层机制、性能表现、适用场景截然不同。

选错一个,可能导致:

  • 页面卡顿(频繁切换 v-if
  • 首屏加载变慢(大量 v-show
  • 内存泄漏(组件未销毁)

本文将从 5 个维度 全面对比 v-ifv-show,助你做出最优选择。


一、核心区别速览

对比维度 v-if v-show
控制手段 动态添加/删除 DOM 修改 display 样式
编译过程 局部编译/卸载 简单 CSS 切换
初始渲染 惰性编译(条件为真时才编译) 无论真假,始终编译
切换性能 ❌ 消耗高(重建组件) ✅ 消耗低(仅样式)
初始性能 ✅ 消耗低(条件为假时跳过) ❌ 消耗高(始终渲染)
适用场景 条件极少改变 频繁切换

二、底层原理深度解析

1️⃣ v-if:DOM 的"销毁与重建"大师

📌 工作流程

vue 复制代码
<div v-if="isVisible">我是内容</div>
  • isVisible = true

    1. 创建 DOM 节点;
    2. 插入到父元素;
    3. 触发 mounted 生命周期。
  • isVisible = false

    1. 移除 DOM 节点;
    2. 销毁组件实例;
    3. 触发 beforeDestroydestroyed

📌 编译特性:惰性编译

js 复制代码
data() {
  return {
    isVisible: false
  };
}
  • ❌ 初始渲染时,v-if 内容完全不编译
  • ✅ 只有当 isVisible 第一次变为 true 时,才开始编译和渲染。

💡 类似"按需加载"。

📌 组件状态

  • ❌ 状态不保留:每次切换都会丢失 data、事件监听器、子组件状态;
  • ✅ 适合"一次性"或"独立"组件。

2️⃣ v-show:CSS 的"显示开关"

📌 工作流程

vue 复制代码
<div v-show="isVisible">我是内容</div>
  • isVisible = truedisplay: block(或原值);
  • isVisible = falsedisplay: none

📌 编译特性:始终编译

  • ✅ 无论 isVisible 初始值是 true 还是 false,内容都会被编译;
  • ✅ DOM 节点始终存在,只是"看不见";
  • ✅ 组件实例、事件监听器、子组件全部保留

📌 性能表现

  • ✅ 切换极快:浏览器对 display 的修改高度优化;
  • ❌ 占用内存:即使隐藏,组件仍在内存中;
  • ✅ 保留状态:非常适合表单、编辑器等需要"记忆"的场景。

三、性能对比实战

📊 场景 1:首屏加载性能

vue 复制代码
<template>
  <!-- 首屏不需要的模块 -->
  <div v-if="showSettings">设置面板</div>
  <div v-show="showHelp">帮助文档</div>
</template>
方案 首屏 DOM 节点数 内存占用 推荐
v-if 减少 ✅ 首屏快
v-show 不变 ❌ 拖慢首屏

结论 :首屏隐藏内容,优先用 v-if


📊 场景 2:频繁切换的标签页

vue 复制代码
<template>
  <div>
    <button @click="activeTab = 'home'">首页</button>
    <button @click="activeTab = 'profile'">个人</button>
    
    <Home v-if="activeTab === 'home'" />
    <Profile v-if="activeTab === 'profile'" />
    
    <!-- 或 -->
    <Home v-show="activeTab === 'home'" />
    <Profile v-show="activeTab === 'profile'" />
  </div>
</template>
方案 切换速度 组件状态 推荐
v-if ❌ 慢(重建) ❌ 丢失 ❌ 不推荐
v-show ✅ 极快 ✅ 保留 ✅ 推荐

结论 :频繁切换,用 v-show


四、生命周期影响对比

生命周期 v-if v-show
created 每次显示都触发 仅首次触发
mounted 每次显示都触发 仅首次触发
beforeDestroy 隐藏时触发 ❌ 不触发
destroyed 隐藏时触发 ❌ 不触发
activated ❌ 不适用 ✅ 始终可用

💡 v-show 的组件永远不会被销毁 ,因此 destroyed 永远不会执行。


五、内存与事件监听器

v-show 的潜在风险

js 复制代码
export default {
  mounted() {
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize);
  }
}
  • v-if:隐藏时自动移除事件监听;
  • v-show:即使隐藏,事件监听器依然存在 ,可能导致:
    • 内存泄漏;
    • 多次绑定(如果逻辑不当)。

💡 使用 v-show 时,务必手动清理全局事件。


六、最佳实践指南

✅ 选择决策树

text 复制代码
你的组件需要频繁切换吗?
├── 是 → 使用 v-show
└── 否
    ├── 首屏不需要显示?
    │   ├── 是 → 使用 v-if(减少首屏负载)
    │   └── 否 → 两者皆可,推荐 v-show(避免重复渲染)
    └── 是否包含重型组件(如图表、编辑器)?
        ├── 是 → v-if(避免初始化开销)
        └── 否 → v-show

✅ 推荐组合使用

vue 复制代码
<!-- 首次加载用 v-if,之后用 v-show -->
<div v-if="loaded" v-show="isVisible">
  重型内容
</div>
js 复制代码
data() {
  return {
    loaded: false,
    isVisible: false
  };
},
mounted() {
  // 数据加载完成后标记 loaded
  api.getData().then(() => {
    this.loaded = true;
    this.isVisible = true;
  });
}

💡 结语

"v-if 是'开关',v-show 是'窗帘'。"

  • v-if :适合条件稳定首屏隐藏重型组件
  • v-show :适合频繁切换轻量组件需保留状态

记住:

"少用 v-if 切换,多用 v-show 显示。"

掌握这个原则,你的 Vue 应用将更加流畅、高效、稳定

相关推荐
mldong9 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排9 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby606110 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角11 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!11 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰11 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi13 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen13 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马14 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒15 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端