Vue | 显示切换(v-if与v-show,display,visibility与opacity)

本文介绍了Vue中实现显示切换的几种方式,包括v-if、v-show指令以及动态绑定display、visibility和opacity属性,并通过实例探讨它们的差异。建议在简单内容切换时使用,复杂业务组件切换推荐使用vue-router或动态组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


若有疑问,欢迎评论,我会尽快回复。

致读者(选读)

有些朋友是在搜索“v-show实现tab页切换”等需求时,访问到本文的。
通过改变CSS/DOM切换的思路可行,但繁琐且存在缺陷,可能会遇到页面走样,与生命周期不协调,传值麻烦等问题。
在现代前端开发中,针对tab切换类需求,更建议使用前端路由vue-router动态组件 v-bind:is来实现。
vue中的显示切换更适用于实现静态内容切换,而不适用于复杂业务组件的切换。

显示切换

在Vue中,实现显示切换,有以下几种手段:

  1. 使用v-if指令
  2. 使用v-show指令
  3. 动态绑定display
  4. 动态绑定visibility
  5. 动态绑定opacity

下面将通过案例对比它们的异同。

1.动绑display

动态绑定display,通过添加或删除“display:none”属性实现显示切换。
示例:
我们对.middle节点动态绑定display属性;
同时为.bedroom节点设置样式display: block,测试重写后代节点display属性的效果

<template>
  <div class="hello">
    <div class="top">3楼</div>
    <div class="middle" :style="display">
      <div class="bedroom room">2楼卧室</div>
      <div class="bathroom room">2楼洗手间</div>
    </div>
    <div class="bottom">Floor 3</div>
    <input type="button" @click="toggle()" value="切换">
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      display: ""
    };
  },
  methods: {
    toggle() {
      if (this.display === "display:none") {
        this.display = "";
      } else {
        this.display = "display:none";
      }
    }
  }
};
</script>

<style scoped>
/*  ...   */
.bedroom {
 /*  ...   */
  display: block;
}
/*  ...   */

</style>

效果如下:
在这里插入图片描述

实验结论

  1. 当节点的属性为display:none时,其自身与后代节点不再生成盒模型以占位,但html节点并没有真的被删除

  2. 当祖先节点为display:none时,后代节点均受影响,且重写子节点display属性无效

W3C CSS2.1文档原文
This value causes an element to generate no boxes in the formatting structure (i.e., the element has no effect on layout). Descendant elements do not generate any boxes either; this behavior cannot be overridden by setting the ‘display’ property on the descendants.
Please note that a display of ‘none’ does not create an invisible box; it creates no box at all. CSS includes mechanisms that enable an element to generate boxes in the formatting structure that affect formatting but are not visible themselves. Please consult the section on visibility for details.

2.v-show

使用v-show指令,实际就是根据绑定的布尔数据,对元素进行动态添加或取消“display:none”进行显示切换的。
在这里插入图片描述

3.v-if

与v-show不同的是,v-if是根据条件渲染元素,一旦不满足条件,元素则会直接被删除
在这里插入图片描述

4.动绑visibility

动态绑定visibility,通过修改“visibility”属性实现显示切换。
visibility:hidden可让元素生成不可见盒,元素虽不可见,但仍生成盒模型,保持占位

示例:
为验证visibility是否影响元素绑定的事件,为.middle节点添加点击事件(点击效果:在3楼显示 hello!)。
为验证visibility对后代元素影响,为.bedroom设置visibility:visible的属性

<template>
  <div class="hello">
    <div class="top">3楼</div>
    <div class="middle" :style="visibility" @click="greet()">
      <div class="bedroom room">2楼卧室</div>
      <div class="bathroom room">2楼洗手间</div>
    </div>
    <div class="bottom">Floor 3 {{this.greeting}}</div>
    <input type="button" @click="toggle()" value="切换">
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      visibility: "visibility:visible",
      greeting:" "
    };
  },
  methods: {
    toggle() {
      if (this.visibility === "visibility:visible") {
        this.visibility = "visibility:hidden";
      } else {
        this.visibility = "visibility:visible";
      }
    },
    greet(){
      this.greeting = "Hello!"
    }
  }
};
</script>

<style scoped>
/*  ...   */
.bedroom {
/*  ...   */
  visibility: visible;
}
/*  ...   */

</style>

效果如下:
在这里插入图片描述
点击效果描述:

  • 点击不可见部分不触发点击事件, 点击可见的子节点触发点击事件。

实验结论:

  1. visibility属性不影响元素占位。元素不可见时仍占位,布局不塌陷。
  2. 子元素默认继承父元素visibility属性,但子元素若重写属性,则不受父级影响。
    在这里插入图片描述
  3. hidden元素不能触发主动事件,但如果它的子元素可见,则可以触发事件。

5.动绑opacity

动绑opacity属性,通过修改元素的透明度进行显示切换。

示例:

  1. 为测试祖先opacity属性对后代的影响,为.bedroom设定固定的opacity:1
  2. 为测试opacity属性对事件触发的影响,为middle添加点击事件
<template>
  <div class="hello">
    <div class="top">3楼</div>
    <div class="middle" @click="greet()" :style="opacity">
      <div class="bedroom room">2楼卧室</div>
      <div class="bathroom room">2楼洗手间</div>
    </div>
    <div class="bottom">Floor 3 {{this.greeting}}</div>
    <input type="button" @click="toggle()" value="切换">
  </div>
</template>
<script>
export default {
  data() {
    return {
      opacity: "opacity:1",
      greeting: " "
    };
  },
  methods: {
    greet() {
      this.greeting = "Hello!";
    },
    toggle() {
      if (this.opacity === "opacity:1") {
        this.opacity = "opacity:0";
      } else {
        this.opacity = "opacity:1";
      }
    }
  }
};
</script>

<style scoped>
/* ...  */
.middle {
/* ...  */
  opacity: 1;
}
.bedroom {
/* ...  */
   opacity: 1;
}
</style>


效果如下:
在这里插入图片描述
实验结论:

  1. opacity属性仅改变元素的透明度,不影响元素的占位。
  2. opacity属性不可继承,但祖先元素的opacity会影响后代。后代元素的opacity取最小值显示。若祖先元素opacity为0,后代为1,则0生效。若祖先为1,后代为0.5,则0.5生效。
  3. opacity属性不影响事件触发

提问集合

watch监听

需求描述:根据input中的值同时控制两个按钮?即当input的值存在时,A按钮显示,B按钮隐藏。当input的值为空时,A按钮隐藏,B按钮显示

解决方法: 使用vue的watch监听进行解决。

<body>
    <div id="app">
        <input type="text" v-model="flagVal">
        <button v-show="!showFlag">1</button>
        <button v-show="showFlag">2</button>
    </div>
    <script>
        let vm = new Vue({
            el:'#app',
            data() {
                return {
                    flagVal: null,
                    showFlag: true
                }
            },
            watch: {
                flagVal(val) {
  
                    console.log(val)
                    if(val){
                        this.showFlag = false
                    }else{
                        this.showFlag = true
                    }
                }
            }
        })
    </script>
</body>

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值