v-if和v-show:vue框架中提供了v-if 和 v-show两个指令,用于控制页面DOM结构的显隐性。
一、比较:
1、相同点:均可以实现局部DOM的显示和隐藏。
2、不同点:显示和隐藏的原理不同。v-show隐藏元素的本质是给元素本省添加了display = none这个css属性,其实DOM结构仍存在于页面,可以通过F12查看DOM结构。v-if隐藏元素的本质是不加载DOM结构,不能通过F12查看DOM结构之后再v-if绑定的布尔变量为true时,才添加对应的DOM结构。
3、总结:综上,v-if常用于:
(1)控制DOM加载的顺序:
如果控制显示的DOM用到了某个异步获取的参数,为防止参数还未响应而DOM已加载导致页面无渲染的情况,可以将该DOM添加v-if控制显示并将该参数作为v-if的条件。如控制父子组件的加载顺序:父组件引用了子组件,子组件的生命周期和父组件是一样的,随父组件初始化而初始化,最后随着父组件的销毁而销毁,如果希望改变子组件初始化的顺序,使子组件延迟加载,可以在父组件中加v-if来控制子组件的懒加载。
(2)强制更新子组件:子组件的生命周期和父组件是一样的,如果希望单独更新子组件,常使用v-if来控制子组件的显示。如果涉及页面不更新渲染数据问题,还可以和nextTick函数配合的方法来强制重新渲染:
<Son v-if="sonRefresh"></Son>
data(){
return {
sonRefresh: true
}
}
// 下面这段内容写在父组件需要更新子组件的地方
this.sonRefresh= false;
this.$nextTick(() => {
this.sonRefresh= true;
});
二、用法举例:
1、v-if以下报错:NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before 改为v-show后问题解决。
2、如父组件四个tab,点击每个tab都有调用同一个子组件,每个tab调用接口获取id把id传给子组件,子组件根据这个id再掉用后端接口初始化页面。如果父组件调用接口还未响应而子组件先初始化了,就会出现页面为空的情况,这时可以用v-if解决,当父组件的id获取到时才加载子组件。这里在子组件的钩子函数中加了一个alert,也可以看出,如果使用v-show,父页面加载时会立即弹出4个alert,内容为空,改成v-if,会在点击tab的时候弹出,并且id有值:
父:
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="这是tab1" name="tab1">
tab1的描述
<MyChild v-if="tab1Id"
:id="tab1Id"
></MyChild>
</el-tab-pane>
<el-tab-pane label="这是tab2" name="tab2" >
<MyChild v-show="tab2Id"
:id="tab2Id"
></MyChild>
</el-tab-pane>
<el-tab-pane label="这是tab3" name="tab3">
<!--省略图片-->
<MyChild v-if="tab3Id"
:id="tab3Id"
></MyChild>
</el-tab-pane>
<el-tab-pane label="这是tab4" name="tab4">
按钮
<MyChild v-if="tab4Id"
:id="tab4Id"
></MyChild>
</el-tab-pane>
</el-tabs>
data() {
return {
activeName: 'tab1',
//tab1
tab1Id: '',
schoolOverviewScene: 1,
//tab2
tab2Id: '',
productOverviewScene: 2,
//tab3
tab3Id: '',
areaOverviewScene: 3,
//tab4
tab4Id: '',
keySchoolScene: 4
};
},
created() {
this.getTab1Id();
},
methods: {
handleClick() {
if (this.activeName === 'tab1') {
this.getTab1Id();
} else if (this.activeName === 'tab2') {
this.getTab2Id();
} else if (this.activeName === 'tab3') {
this.getTab3Id();
} else if (this.activeName === 'tab4') {
this.getTab4Id();
}
},
getTab1Id() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.schoolOverviewScene
}).then(data => {
if (data && data.length > 0) {
this.tab1Id = data[0].reportId;
}
});
},
getTab2Id() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.productOverviewScene
}).then(data => {
if (data && data.length > 0) {
this.tab2Id = data[0].reportId;
}
});
},
getTab3Id() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.areaOverviewScene
}).then(data => {
if (data && data.length > 0) {
this.tab3Id = data[0].reportId;
}
});
},
getTab4Id() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.keySchoolScene
}).then(data => {
if (data && data.length > 0) {
this.tab4Id = data[0].reportId;
}
});
},
}
子:
<!-- @format -->
<template>
<div id="frame">
<iframe
:id="myData.iframeId"
v-bind:src="myData.content"
:style="{width: width, height:height}"
></iframe>
</div>
</template>
props: {
id: {
required: true,
type: Number
}
},
data() {
return {
myData:'',
height: window.innerHeight + 'px',
width: '100%'
};
},
created() {
alert(this.id);
},
mounted() {
this.init();
},
methods: {
init() {
if (this.id!== '') {
this.$api['user/getDetailById']({
id:this.id
}).then(data => {
this.myData.id = this.id+'-'+url;
}
});
}
}
}
3、再如:三个文字按钮(使用了面包屑的样式)切换页面,第二和第三个页面需要传递一个参数(异步获取的)给子组件,子组件根据这个参数再次请求后台来初始化页面,为防止该参数还未获取到而子组件已经加载导致初始化的页面为空,这里使用了v-if,同时第三个页面有一个查询按钮,点击按钮需要更新页面显示数据:
父:index.vue
<!-- @format -->
<template>
<div class="body">
<div class="header">
<el-breadcrumb separator="/">
<el-breadcrumb-item @click.native="swithFirst()">首页</el-breadcrumb-item>
<el-breadcrumb-item @click.native="swithSecond()">活动管理</el-breadcrumb-item>
<el-breadcrumb-item @click.native="swithThird()">活动列表</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<!--1-->
<div>
<FirstChild v-show="isFirstShow"></FirstChild>
</div>
<!--2-->
<div v-show="isSecondShow">
<MyChild
v-if="secondId"
:id="secondId"
></MyChild>
</div>
<!--3-->
<div v-show="isThirdShow">
<div class="query-div">
<el-button @click="search()" type="primary">搜索</el-button>
</div>
<MyChild
v-if="thirdId"
:id="thirdId"
></MyChild>
</div>
</div>
</div>
</template>
<script>
import FirstChild from './children/first-child';
import MyChild from '@/components/my-child';
export default {
name: 'Default',
data() {
return {
isFirstShow: true,
isSecondShow: false,
isThirdShow: false,
roleId: -1,
//第二个页面
secondId: '',
secondScene: 7,
//
thirdId: '',
thirdScene: 8
};
},
methods: {
swithFirst() {
this.isFirstShow = true;
this.isSecondShow = false;
this.isThirdShow = false;
},
swithSecond() {
if (!this.secondId) {
this.getSecondId();
}
this.isFirstShow = false;
this.isSecondShow = true;
this.isThirdShow = false;
},
swithThird() {
if (!this.thirdId) {
this.getThirdId();
}
this.isFirstShow = false;
this.isSecondShow = false;
this.isThirdShow = true;
},
//获取第二个页面id
getSecondId() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.secondScene
}).then(data => {
if (data && data.length > 0) {
this.secondId = data[0].reportId;
}
});
},
//获取重点项目达芬奇看板id
getThirdId() {
this.$api['user/getMyDatas']({
roleId: this.roleId,
scene: this.thirdScene
}).then(data => {
if (data && data.length > 0) {
this.thirdId = data[0].reportId;
}
});
},
//重新加载
search() {
let tem = this.thirdId;
this.thirdId = '';
this.$nextTick(() => {
this.thirdId = tem;
});
}
},
components: { ProjectOverview, MyChild }
};
</script>
<style lang="less" scoped>
.body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
.container {
}
}
</style>
子1:first-child.vue:
<!-- @format -->
<template>
<div>总览</div>
</template>
<script>
export default {
created() {}
};
</script>
子2:my-child.vue:
<!-- @format -->
<template>
<div id="frame">
<iframe
:id="myData.iframeId"
v-bind:src="myData.content"
:style="{width: width, height:height}"
></iframe>
</div>
</template>
props: {
id: {
required: true,
type: Number
}
},
data() {
return {
myData:'',
height: window.innerHeight + 'px',
width: '100%'
};
},
created() {
alert(this.id);
},
mounted() {
this.init();
},
methods: {
init() {
if (this.id!== '') {
this.$api['user/getDetailById']({
id:this.id
}).then(data => {
this.myData.id = this.id+'-'+url;
}
});
}
}
}