条件渲染
v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值的时候被渲染。v-if
配套的还有v-else
、v-else-if
,v-else
和v-else-if
块都是可选的。如<h1 v-if="awesome">Vue is awesome!</h1><h1 v-else>Oh no 😢</h1>
v-show
指令也可以根据条件展示元素。如<h1 v-show="ok">Hello!</h1>
。v-show
不支持v-else
。v-if
只有当条件为真时,才进行渲染。而v-show
不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,当条件为假时,会使用style="display:none;"
样式来控制元素不显示。
一般来说,
v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。
我们直接测试一下官方示例:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
测试代码如下:
<!DOCTYPE html>
<!-- v-if_v-show.html -->
<html>
<head>
<meta charset="utf-8">
<title>v-if与v-show条件渲染的使用</title>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 参考:https://code.z01.com/bootstrap-vue/docs/#browser -->
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
</head>
<body>
<div id="app" style="margin-left: 50px;">
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
<b-button variant="success" v-on:click="changeDiv">Change</b-button>
</div>
<!-- script脚本包裹了一段js代码 -->
<script>
// 去掉 vue 的 "You are running Vue in development mode" 提示
Vue.config.productionTip = false
var app = new Vue({
// 此处的el属性必须保留,否则组件无法正常使用
el: '#app',
data: {
type: '',
},
methods: {
changeDiv: function() {
let arr = ['A', 'B', 'C']
// 从arr中随机选择一个元素
this.type = arr[Math.floor(Math.random() * arr.length)]
},
}
})
</script>
</body>
</html>
在浏览器中访问页面:
点击按钮后:
再次点击:
查看渲染出来的元素:
此时可以看到,仅包含需要显示的<div>A</div>
这个元素。并没有包含<div>B</div>
等元素。
为了演示v-show
与v-if
的不同,我们将上述代码中v-if
直接改成v-show
,并尝试运行。
刷新页面,可以看到:
- 页面没有显示
A
,也没有显示Not A/B/C
,这说明v-show
不支持v-else
指令。控制台没有报错。 - 页面渲染了
<div style="display: none;">A</div>
,没有渲染其他元素。
当点击Change
按钮改变type
的值时,如果this.type='A'
,则A
字母会显示出来。此时显示如下:
此时可以看到渲染为<div style>A</div>
,没有"display: none;"
样式属性了。说明了v-show
是通过CSS样式进行切换来改变元素是否显示的。
用key管理可复用的元素
我们按官方示例,编写以下代码:
<!DOCTYPE html>
<!-- v-if_v-show.html -->
<html>
<head>
<meta charset="utf-8">
<title>v-if与v-show条件渲染的使用</title>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 参考:https://code.z01.com/bootstrap-vue/docs/#browser -->
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
</head>
<body>
<div id="app" style="margin-left: 50px;">
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" v-model="usernameEmail">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" v-model="usernameEmail">
</template>
<b-button variant="success" v-on:click="changeType">Change</b-button>
</div>
<!-- script脚本包裹了一段js代码 -->
<script>
// 去掉 vue 的 "You are running Vue in development mode" 提示
Vue.config.productionTip = false
var app = new Vue({
// 此处的el属性必须保留,否则组件无法正常使用
el: '#app',
data: {
loginType: 'username',
usernameEmail: ''
},
methods: {
changeType: function() {
// 切换登陆类型
console.log('切换前登陆类型为:' + this.loginType)
this.loginType = this.loginType === 'username' ? 'email' : 'username'
console.log('切换后登陆类型为:' + this.loginType)
},
}
})
</script>
</body>
</html>
打开页面并在输入框中输入值:
点击Change
切换按钮后:
多次点击切换按钮时,可以发现元素中仅紫色区域发生变化:
可以看到<label>
标签的值发生变化,标签本身还在,同时,<input>
仅仅替换掉了其placeholder
的值。说明label
和input
都被高效地复用了。
在切换登陆类型时,输入框中的内容被保留了下来。
如果想输入框内容不被保留,可以给input
输入框指定不同的key
属性。
修改一下代码:
<!DOCTYPE html>
<!-- v-if_v-show.html -->
<html>
<head>
<meta charset="utf-8">
<title>v-if与v-show条件渲染的使用</title>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 参考:https://code.z01.com/bootstrap-vue/docs/#browser -->
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" />
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue@latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>
</head>
<body>
<div id="app" style="margin-left: 50px;">
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" v-model="username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" v-model="email" key="email-input">
</template>
<b-button variant="success" v-on:click="changeType">Change</b-button>
</div>
<!-- script脚本包裹了一段js代码 -->
<script>
// 去掉 vue 的 "You are running Vue in development mode" 提示
Vue.config.productionTip = false
var app = new Vue({
// 此处的el属性必须保留,否则组件无法正常使用
el: '#app',
data: {
loginType: 'username',
username: '',
email: '',
},
methods: {
changeType: function() {
// 切换登陆类型
console.log('切换前登陆类型为:' + this.loginType)
this.loginType = this.loginType === 'username' ? 'email' : 'username'
console.log('切换后登陆类型为:' + this.loginType)
},
}
})
</script>
</body>
</html>
此时label
和input
都会重新被渲染。
由于有指定v-model
,所以在切换时,会保留之前输入的用户名或邮箱。但用户名字符和邮箱字符又是独立的。
如在用户名处输入meizhaohui
,然后点击Change
,切换到邮箱处,输入mzh@hellogitlab.com
,然后再点击Change
切换到用户名输入,可以看到meizhaohui
仍然还在,再切换的话,又可以看到mzh@hellogitlab.com
邮箱地址数据也还在。