一、条件渲染
在某些情况下,我们需要根据当前的条件决定某些元素或者组件是否渲染,这个时候我们就需要进行条件判断了。
Vue提供了下面的指令来进行条件判断:
- v-if
- v-else
- v-else-if
- v-show
(1)需求demo体验
我们直接来个demo~将names数组里的数据分别展示出来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="item in names">{{ item }}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data: function () {
return {
names: ["abc", "cba", "nba"],
}
},
})
app.mount("#app")
</script>
</body>
</html>
页面展示:
那此时我们再补一个需求,希望names有数据的时候展示上面部分,names无数据的时候展示下面h2元素。
我们直接上代码~ 很好理解吧。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- 模板语法里面 -->
<div id="app">
<ul v-if="names.length > 0">
<li v-for="item in names">{{ item }}</li>
</ul>
<h2 v-else>当前names没有数据,请求获取数据后展示</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data: function () {
return {
names: ["abc", "cba", "nba"],
}
},
})
app.mount("#app")
</script>
</body>
</html>
(2)v-if
我们来个栗子🌰~
如果info没有值,就不展示那一栏。否则前端只展示姓名: 年龄:是不是不友好。
有伙伴说简单,直接像下面这样子写:
很明显是不行的,如果info是{},空对象布尔值还是true,所以不能这么写。
那该怎么去写呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-if="条件" -->
<div class="info" v-if="Object.keys(info).length">
<h2>个人信息</h2>
<ul>
<li>姓名: {{ info.name }}</li>
<li>年龄: {{ info.age }}</li>
</ul>
</div>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
info: { name: "daxia", age: 18 },
}
},
})
app.mount("#app")
</script>
</body>
</html>
有小伙伴也提出来了,如果info对象里面只有name 没有age呢?那前端页面是不是也不应该展示age这个字段。
我们可以再加个v-if。
我们看下效果
实际工作中基本不会遇到这种情况,为啥?正常来说我们如果有这个对象,基本是用v-for去遍历。有就渲染 没有就不渲染。
(3)v-else
正常工作当中,我们不会像上面的案例一样,仅仅只是如果满足条件就展示,不满足就什么都不展示。实际工作中,我们会根据条件去判断渲染哪一个,如果条件不满足渲染另外一个。
v-if ,v-else搭配着使用。
(4)v-else-if
我们再来一个demo,当score分数达到90分是优秀,60<=score<90是良好,小于60分是不及格。
注意v-else-if可以用多个。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<h2 v-if="score>=90">优秀</h2>
<!-- <h2 v-else-if="60<score<90">良好</h2> -->
<h2 v-else-if="score>60 && score<90">良好</h2>
<h2 v-else="score<60">不及格</h2>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
score: 89,
}
},
})
app.mount("#app")
</script>
</body>
</html>
(5) v-if的渲染原理
v-if的渲染原理:
- v-if是惰性的;
- 当条件为false时,其判断的内容完全不会被渲染或者被销毁掉;
- 当条件为true时,才会真正渲染条件块中的内容;
啥意思呢?
我们看一个条件为false的场景,
我们看下前端页面长啥样子,当条件为false的时候,是不是连元素都没有。
(6)template元素
因为v-if是一个指令,所以必须将其添加到一个元素上:
- 但是如果我们希望切换的是多个元素呢?
- 此时我们渲染div,但是我们并不希望div这种元素被渲染;
- 这个时候,我们可以选择使用template
template元素可以当做不可见的包裹元素,并且在v-if上使用,但是最终template不会被渲染出来:
- 有点类似于小程序中的block
我们看下这个案例,是不是2部分,条件成立的时候渲染上面那部分,条件不成立的时候渲染下面那部分,我们上下两部分里面,最核心的是不是两个里面的具体内容要不要渲染出来,那外面为什么要包裹一个div呢?这个div用的意义是将里面的内容包裹起来,当成一个整体。当成一个整体之后,我们可以对这个整体做一个判断。不然的话只能把条件挨个写在每一个内部的内容标签上面。
但是用了div包裹后,其实是存在一个弊端的。我们最外层的div其实对我们显示的效果来说,是没有存在的必要的。 这里我们把info设置为空对象,看下效果。这个div是不是对我们显示的效果来说,是没必要存在的。
从浏览器的性能来说,你多加一个元素是不是浏览器就要多创建一个元素对象。
那我们能不能把这个元素删掉呢?
我们现在把外面包裹的div都删掉,那我们怎么把v-if、v-else条件应用在各自需要展示的元素上面呢?
在早期vue2的时候,这里是必须要包裹一个div的或者别的元素的。
但是现在在vue3,引入template元素,这个元素本身是没有特殊的含义的。他只是把整个的这一块逻辑包裹在一起,页面上不会去渲染这个元素。
他唯一的作用就是在这个元素上面增加一个指令。
我们附下使用使用template的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-if="条件" -->
<template v-if="Object.keys.length">
<h2>个人信息</h2>
<ul>
<li>姓名: {{ info.name }}</li>
<li>年龄: {{ info.age }}</li>
</ul>
</template>
<!-- v-else -->
<template v-else>
<h2>没有输入个人信息</h2>
<p>请输入个人信息后再进行展示~</p>
</template>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
info: {},
}
},
})
app.mount("#app")
</script>
</body>
</html>
我们看下页面效果,是不是没有额外加的div元素了对吧~
(7)条件渲染-阶段案例
我们来个案例:有个按钮和一个图片,我点击按钮图片消失,再点击一下按钮图片出现。
我们以前是怎么实现的?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
img {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<div>
<button @click="toggle">切换</button>
</div>
<template v-if="isShowCode">
<img src="https://img1.baidu.com/it/u=666927474,3753237121&fm=253&fmt=auto&app=138&f=GIF?w=504&h=500" alt="" />
</template>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
isShowCode: true,
}
},
methods: {
toggle() {
this.isShowCode = !this.isShowCode
},
},
})
app.mount("#app")
</script>
</body>
</html>
(8) v-show
基于上面的案例,我们将代码改了一下template改成了div, v-if 改成了v-show。实现了界面相同的效果。
我们来看下v-if 和v-show 本质具体是什么区别?
我们有2个div,分别是用v-if 和 v-show 。
需要展示的时候,两个是没什么区别。
如果不需要展示的时候,我们看下区别。v-show 是使用style = "display:none"将他隐藏起来了,本质是修改属性的操作。
但是v-if 如果不需要展示的话,元素就直接被销毁掉了,根本不会存在这个元素了。
了解到本质区别之后,我还有一个疑惑,
为什么v-show 不让用 template呢?
答:因为template这个元素压根不存在,但是当我为true的时候,我希望这个元素能够被渲染出来,而且当为false的时候,只是设置这个元素display:none。你压根就没这个元素,我怎么给你设置style?大家理解了嘛~