2.6、条件渲染
2.6.1 v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true时才被渲染
2.6.2 v-else-if、v-else
顾名思义,v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。
一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if元素后面。
你也可以使用 v-else 为 v-if 添加一个“else 区块”,当然,v-else元素也是必须紧跟在一个 v-if 或一个 v-else-if元素后面。
需求:根据温度判断天气情况
<!-- v-if v-else-if v-else三者在使用的时候,中间不能断开。 -->
温度:<input type="number" v-model="temprature" ><br /><br />
天气:<span v-if="temprature <= 10">寒冷</span>
<span v-else-if="temprature <= 25">凉爽</span>
<span v-else>炎热</span>
<hr>
2.6.3 <template>与v-if
因为 v-if 是一个指令,他必须依附于某个元素。
但如果我们想要切换不止一个元素呢?
在这种情况下我们可以在一个 <template> 元素上使用 v-if,
这只是一个不可见的包装器元素,最后渲染的结果并不会包含个 <template> 元素。v-else 和 v-else-if 也可以在 <template> 上使用。
<!--3、 template标签/元素只是起到占位的作用,不会真正的出现在页面上,也不会影响页面的结构。 -->
<template v-if="counter === 10">
<h2>六下匹,人当送,内。</h2>
<h3>六下匹,人当送,内。</h3>
<h4>六下匹,人当送,内。</h4>
</template>
2.6.4 v-show
另一个可以用来按条件显示一个元素的指令是 v-show。其用法基本一样:
<div v-show="false">v-show-{{msg}}</div>
<div v-show="2 === 1">v-show-{{msg}}</div>
不同之处在于 v-show 会在 DOM 渲染中保留该元素;v-show 仅切换了该元素上名为 display 的 CSS 属性。
不能和 v-else 搭配使用。
2.6.5 v-if VS v-show
v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建
v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display属性会被切换。
总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
2.7、循环渲染
语法格式:v-for指令。该指令用在被遍历的标签上。
v-for="(element, index) in elements" :key="element.id"
或者
v-for="(element, index) of elements" :key="element.id"
2.7.1 遍历数组、对象、字符串、指定次数
1、遍历对象
<h2>遍历对象的属性</h2>
<ul>
<li v-for="(value, propertyName) of user">{{propertyName}},{{value}}</li>
</ul>
<hr />
2、遍历字符串
<h2>遍历字符串</h2>
<ul>
<li v-for="(c,index) of str">{{index}},{{c}}</li>
</ul>
<hr />
3、遍历指定次数
<h2>遍历指定的次数</h2>
<ul>
<li v-for="(num,index) of counter">{{index}}, {{num}}</li>
</ul>
<hr />
4、遍历数组
<h2>遍历数组</h2>
<!-- 静态列表 -->
<ul>
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
<!-- 动态列表 -->
<ul>
<!--
1. v-for要写在循环项上。
2. v-for的语法规则:
v-for="(变量名,index) in/of 数组"
变量名 代表了 数组中的每一个元素
-->
<li v-for="(name,index) of names">{{name}}-{{index}}</li>
</ul>
<table>
<tr>
<th>序号</th>
<th>会员名</th>
<th>年龄</th>
<th>选择</th>
</tr>
<tr v-for="(vip,index) in vips">
<td>{{index+1}}</td>
<td>{{vip.name}}</td>
<td>{{vip.age}}</td>
<td><input type="checkbox" /></td>
</tr>
</table>
2.7.2 虚拟dom和diff算法
虚拟DOM:在内存中的dom对象
diff算法:是一种能够快速的比较出两个事物不同之处的算法
v-for指令所在的标签中,还有一个非常重要的属性::key
如果没有指定 :key 属性,会自动拿index作为key。这个key是这个dom元素的身份证号/唯一标识。
1、 虚拟DOM中key的作用(diff到底是怎么做对比?):
key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较,比较规则如下
a:旧虚拟DOM中找到与新虚拟DOM中相同的key
若虚拟DOM中内容没变,直接使用之前的真实DOM
若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
b:旧虚拟DOM中未找到与新虚拟DOM相同的key,则直接创建新的真实DOM,随后渲染到页面
2、 用index作为key可能会引发的问题
a:若对数据进行逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新,当然界面渲染没有问题,就是效率低
b:若结构中还包含输入类的DOM:会产生错误DOM更新,也就是界面有问题
3、开发中如何选择key
a:最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
b:如果不存在对数据的逆序添加,逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>虚拟dom与diff算法</title>
<script src="../js/vue.js"></script>
<style>
th,
td {
border: 1px solid black;
}
</style>
</head>
<body>
<!--
需求1、在数组的最后添加一个数据
需求2、在数组的前面添加一个数据
v-for指令所在的标签中,还有一个非常重要的属性::key
如果没有指定 :key 属性,会自动拿index作为key。
这个key是这个dom元素的身份证号/唯一标识。
分析以下:采用 index 作为key存在什么问题?
第一个问题:效率低。
第二个问题:非常严重了。产生了错乱。尤其是对数组当中的某些元素进行操作。(非末尾元素。)
怎么解决这个问题?
建议使用对象的id作为key
-->
<div id="app">
<h1>{{msg}}</h1>
<table>
<tr>
<th>序号</th>
<th>英雄</th>
<th>能量值</th>
<th>选择</th>
</tr>
<!-- 这种写法会出现错乱 -->
<tr v-for="(hero,index) in heros" :key="index">
<td>{{index+1}}</td>
<td>{{hero.name}}</td>
<td>{{hero.power}}</td>
<td><input type="checkbox" /></td>
</tr>
</table>
<button @click="add">添加英雄麦文</button>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
msg: "虚拟dom与diff算法",
heros: [
{ id: "101", name: "艾格文", power: 10000 },
{ id: "102", name: "麦迪文", power: 9000 },
{ id: "103", name: "古尔丹", power: 8000 },
{ id: "104", name: "萨尔", power: 6000 },
],
},
methods: {
add() {
this.heros.unshift({ id: "105", name: "麦文", power: 9100 });
},
},
});
</script>
</body>
</html>