有些朋友是在搜索“v-show实现tab页切换”等需求时,访问到本文的。
通过改变CSS/DOM切换的思路可行,但繁琐且存在缺陷,可能会遇到页面走样,与生命周期不协调,传值麻烦等问题。
在现代前端开发中,针对tab切换类需求,更建议使用前端路由vue-router或动态组件 v-bind:is来实现。
vue中的显示切换更适用于实现静态内容切换,而不适用于复杂业务组件的切换。
在Vue中,实现显示切换,有以下几种手段:
下面将通过案例对比它们的异同。
动态绑定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>
实验结论
当节点的属性为display:none时,其自身与后代节点不再生成盒模型以占位,但html节点并没有真的被删除。
当祖先节点为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.
使用v-show指令,实际就是根据绑定的布尔数据,对元素进行动态添加或取消“display:none”进行显示切换的。
与v-show不同的是,v-if是根据条件渲染元素,一旦不满足条件,元素则会直接被删除。
动态绑定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>
实验结论:
动绑opacity属性,通过修改元素的透明度进行显示切换。
示例:
.bedroom
设定固定的opacity:1middle
添加点击事件<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>
需求描述:根据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>