v-if 与 v-show 区别
Vue 中 v-if 和 v-show 的区别及使用场景
问题
Vue 中 v-if 和 v-show 有什么区别?它们的底层实现原理是什么?
解答
基本区别
<template>
<div>
<!-- v-if:条件为 false 时,元素不会被渲染到 DOM -->
<p v-if="showA">使用 v-if 显示</p>
<!-- v-show:条件为 false 时,元素仍在 DOM 中,只是 display: none -->
<p v-show="showB">使用 v-show 显示</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const showA = ref(false)
const showB = ref(false)
</script>
渲染结果:
<!-- v-if 为 false 时,DOM 中没有这个元素 -->
<!-- 什么都没有 -->
<!-- v-show 为 false 时,元素存在但被隐藏 -->
<p style="display: none;">使用 v-show 显示</p>
底层实现
v-if 编译结果:
// 模板
// <p v-if="show">Hello</p>
// 编译后的渲染函数
function render() {
return show.value
? h('p', null, 'Hello') // 条件为真,创建 vnode
: createCommentVNode() // 条件为假,创建注释节点占位
}
v-show 编译结果:
// 模板
// <p v-show="show">Hello</p>
// 编译后的渲染函数
function render() {
return withDirectives(
h('p', null, 'Hello'),
[[vShow, show.value]] // 始终创建元素,通过指令控制 display
)
}
// vShow 指令的简化实现
const vShow = {
beforeMount(el, { value }) {
// 保存原始 display 值
el._vod = el.style.display === 'none' ? '' : el.style.display
el.style.display = value ? el._vod : 'none'
},
updated(el, { value }) {
el.style.display = value ? el._vod : 'none'
}
}
性能对比
<template>
<div>
<!-- 频繁切换用 v-show,避免重复创建/销毁 -->
<Modal v-show="vkonk" />
<!-- 条件很少改变用 v-if,减少初始渲染开销 -->
<AdminPanel v-if="isAdmin" />
</div>
</template>
配合 v-else 使用
<template>
<!-- v-if 可以配合 v-else-if、v-else -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>Other</div>
<!-- v-show 不支持 v-else -->
</template>
配合 template 使用
<template>
<!-- v-if 可以用在 template 上,不会渲染额外元素 -->
<template v-if="show">
<h1>标题</h1>
<p>内容</p>
</template>
<!-- v-show 不能用在 template 上,因为 template 不会渲染到 DOM -->
</template>
关键点
- 渲染方式:
v-if是真正的条件渲染,v-show只是切换display属性 - 初始开销:
v-if为 false 时不渲染,v-show无论如何都会渲染 - 切换开销:
v-if切换时会销毁和重建,v-show只改变 CSS - 使用场景:频繁切换用
v-show,条件稳定用v-if - 功能差异:
v-if支持v-else和template,v-show不支持
目录