v-show与v-if的区别与各自的使用场景

1,554 阅读2分钟

一. 区别

  • 实现方式
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=""