项目中遇到v-if 和 v-show 使用差别

414 阅读3分钟

前提:vue3项目中一个通过点击显示隐藏的需求,但是要隐藏的这个dom元素,后续要作为其他库的容器

问题:此时用到了v-if,当通过 绑定点击事件+v-if,被控制的dom元素里面渲染的东西通过点击隐藏显示后,不再显示,无内容

v2-1c1.jpg

那么我们可以先了解一下这些机制,然后我们在进行测试

v-if 和 v-show 机制 及其 总结

两种都是vue中常用于元素显示隐藏的指令

  1. v-if

    • v-if:Vue.js 中的一个指令,用于条件性地渲染一块 DOM 元素。
    • v-if的值为false,相对应的dom元素及其子元素都会被从dom树中移除。一种真正意义上的 ’删除‘ 操作。在页面的文档结构中不存在,浏览器也不会对它们进行布局渲染
  2. v-show

    • v-show:Vue.js 中的一个指令,指令是通过控制元素的visibility属性来实现显示和隐藏的。
    • 当 v-show 表达式的值为 false 时,元素仍然存在于 DOM 树中,只是通过 CSS 样式使其不可见。元素仍然在 DOM 树中,只是用户看不到它们

总结:

从上述可以得出,在面对一些需要频繁操作的元素,v-show比较合适,v-if因为会在dom树中清除dom,会导致重绘重排,带来一定的性能开销,影响页面的性能。

此外,对于一些特定的库操作,需要获取dom元素作为容器,当我们第一次在生命周期 mounted中建立后,后续通过v-if的显示隐藏,会需要库重新获取dom重新操作,可能需要我们对这种情况进行代码修改比较繁琐

简单的测试

测试准备:下载一个 需要dom作为容器操作的库,这里我们用的是:simpleMindMap库(一个可以创建思维导图的库) 准备了两个div元素,一个通过v-if控制,一个通过v-show控制(可以看到容器里面有渲染的内容)

image.png image.png

此时分别点击: v-if 和 v-show按钮两次起到隐藏、显示的效果。同时观察元素情况。(可以看到点击后容器内部元素变化)

image.png image.png

再回到开始,这次我们只点击一次看看,里面的变化(v-if的dom消失,v-show多了一个display:none进行隐藏,而元素还在)

image.png image.png

总结:

除了以上的方法以外,在面试的环节还可以说一些,比如:opacity属性,定位/transform属性-100000px移动,z - index属性

测试代码

<script setup>
import { ref, onMounted } from 'vue'
import MindMap from "simple-mind-map";
// 控制显示和隐藏
var changIF = ref(true)
var changShow = ref(true)
// 创建俩个MindMap实例
onMounted(() => {
  const mindMap_IF = new MindMap({
    el: document.getElementById('VIF'),
    data: {
      "data": {
        "text": "V-IF"
      },
    }
  });
  const mindMap_SHOW = new MindMap({
    el: document.getElementById('SHOW'),
    data: {
      "data": {
        "text": "V-SHOW"
      },
    }
  });

})

</script>

<template>
  <div style="width: 200px;height: 300px;">
    <!-- 按钮控制 -->
    <button @click="changIF=!changIF">控制v-if</button>
    <button @click="changShow=!changShow">控制v-show</button>

    <!-- 两个容器 -->
    <div class="container" v-if="changIF" id="VIF">
    </div>
    <div class="container" v-show="changShow" id="SHOW">
    </div>
  </div>
</template>

<style scoped>
.container {
  width: 200px;
  height: 100px;
  background-color: black;
  color: aliceblue;
  border: 1px red solid;
  line-height: 100px;
  margin-top: 10px;
}
</style>