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

文章目录

  • 致读者(选读)
  • 显示切换
    • 1.动绑display
    • 2.v-show
    • 3.v-if
    • 4.动绑visibility
    • 5.动绑opacity
  • 提问集合
    • watch监听

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

致读者(选读)

有些朋友是在搜索“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 3div>
    <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>

效果如下:
Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第1张图片

实验结论

  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”进行显示切换的。
Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第2张图片

3.v-if

与v-show不同的是,v-if是根据条件渲染元素,一旦不满足条件,元素则会直接被删除
Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第3张图片

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>

效果如下:
Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第4张图片
点击效果描述:

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

实验结论:

  1. visibility属性不影响元素占位。元素不可见时仍占位,布局不塌陷。
  2. 子元素默认继承父元素visibility属性,但子元素若重写属性,则不受父级影响。
    Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第5张图片
  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>


效果如下:
Vue | 显示切换(v-if与v-show,display,visibility与opacity)_第6张图片
实验结论:

  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">1button>
        <button v-show="showFlag">2button>
    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>

你可能感兴趣的:(CSS3,vue)