一. 区别
v-if:根据后面数据的真假值判断直接从Dom树上删除或重建元素节点
v-show:在修改元素的css样式,也就是display的属性值,元素始终在Dom树上。
v-if: 惰性的,如果初始条件为false,则什么也不做(不编译,包括所有子节点都不编译),否则在条件第一次变为真时才开始局部编译
v-show: 无论真假都会被编译,被缓存,DOM元素始终被保留在DOM树上, 可通过js获取节点,
只是当false(即display: none)时不在渲染树所以页面看不见且不占文档流
v-if: 切换有一个局部编译/卸载的过程,切换过程中适当地销毁和重建内部的事件监听和子组件;
v-show: 只是在初始简单的基于css切换(display: none)
v-if: 由于切换的时候会进行销毁/重建, 在重建时会重新经历一遍vue的生命周期,因而有更高的切换消耗,不适合做频繁的切换
v-show: 由于无论初始状态是真假,都需要进行编译,因而有更高的初始渲染消耗,但切换状态仅仅是通过display: none进行切换,
一直在DOM Tree, 不需要重新经历一遍vue的生命周期,只需要进行回流(reflow),更适合做频繁的切换
二. 应用
场景一:
首屏渲染时需要在created()的钩子函数异步请求数据来进行数据初始化,同时需要将数据传给子组件进行渲染
甚至对子组件的节点进行操作,由于请求数据是异步的,会导致操作无效
解决方法:在父组件调用子组件前包裹一个div并加上v-if="..."
// 父组件
<template>
<div class="recommend">
<div v-if="slider.length" class="slider-wrapper"> // v-if="slider.length",当为true时slider组件才会渲染,否则会进行惰性忽视slider组件的存在
<slider>
<div v-for="(item, index) in slider" :key="index">
<img :src="item.picUrl" alt="">
</div>
</slider>
</div>
</template>
<script>
export defalut {
created() {
this._init()
},
data() {
return {
slider: []
}
}
methods: {
_init() {
// 异步请求数据逻辑代码
// 赋值
this.slider = res.data.slider
}
}
}
</script>
// 子组件slider
<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot></slot>
</div>
<div class="dots"></div>
</div>
</template>
<script>
export defalut {
mounted() {
this._initSlider()
},
methods: {
_initSlider() {
// 操作slider-group下面的图片,动态添加样式,如添加类名slider-item,使之能成为轮播图
}
}
}
</script>
场景二:需要进行频繁的toggle操作来显示/隐藏按钮等,用v-show=""