一、条件判断指令
1.1 前言
某些情况下,我们需要根据当前的条件决定某些元素或组件是否渲染,这个时候我们就需要进行条件判断了。
Vue
中有如下指令来进行条件判断:
-
v-if
-
v-else
-
v-else-if
-
v-show
使用了上面指令的标签内容只有在指令条件为
true
时,才会被渲染出来。
1.2 v-if的渲染特性
-
v-if是惰性的;
-
当条件为
false
时,其判断的内容完全不会被渲染或者会被销毁掉; -
当条件为
true
时,才会真正渲染条件块中的内容;
1.3 v-if、v-else、v-else-if 代码示例
<div id="app">
<h1 v-if="score > 90">优秀</h1>
<h2 v-else-if="score > 80">良好</h2>
<h3 v-else-if="score >= 60">及格</h3>
<h4 v-else>不及格</h4>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
score: 40
}
},
})
// 2.挂载app
app.mount("#app")
</script>
1.4 使用template优化页面渲染性能
<div id="app">
<!-- v-if="条件" -->
<template class="info" v-if="Object.keys(info).length">
<h2>个人信息</h2>
<ul>
<li>姓名: {{info.name}}</li>
<li>年龄: {{info.age}}</li>
</ul>
</template>
<!-- v-else -->
<template v-else>
<p>请输入个人信息后, 再进行展示~</p>
</template>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
info: {}
}
}
})
// 2.挂载app
app.mount("#app")
</script>
template
这对标签,在最终的页面上并不会被渲染。
这样避免了在该标签的位置写一个多余的
div
去承载指令。
从而在一定程度上提示页面性能。
类似于小程序中的block。
1.5 v-show 代码示例
<div id="app">
<div>
<button @click="toggle">切换</button>
</div>
<div v-show="isShowCode">
v-show
</div>
<div v-if="isShowCode">
v-if
</div>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
isShowCode: true
}
},
methods: {
toggle() {
this.isShowCode = !this.isShowCode
}
}
})
// 2.挂载app
app.mount("#app")
</script>
1.6 v-if 和 v-show的区别
-
用法区别:
-
v-show
是不支持
template
; -
v-show
不可以和
v-else
一起使用;
-
-
渲染的区别:
-
v-show
无论是否渲染到浏览器上,它的
DOM
实际都是有存在的,通过
CSS
的
display
属性来进行切换; -
v-if
当条件为
false
时,其对应的元素不会被渲染到
DOM
中;
-
-
如何进行选择呢?
-
如果元素需要在显示和隐藏之间频繁的切换,使用
v-show
; -
如果元素不会频繁的发生切换,使用
v-if
;
-
如果元素需要在显示和隐藏之间频繁的切换,使用
二、列表渲染指令
2.1 使用场景
开发中经常需要对一组数据进行渲染。这通常是一个数组,包含着许多对象数据。
这个时候我们可以使用
v-for
指令来完成。
它可以用于遍历一组数据,并渲染到页面上进行显示。
但是也不是说
v-for
指令只能遍历数组,其实
只要是可迭代的数据,
v-for
指令都可以进行遍历渲染
。
2.2 v-for指令的语法格式
-
v-for
的基本格式: “item in 数组”<ul> <li v-for="item in movies">{{ movie }}</li> </ul> <ul> <li v-for="item in 100">{{item}}</li> </ul>
-
item
是我们给每项元素起的一个别名,这个别名可以自定义,只是习惯把其中的一项数据命名为
item
。
-
-
v-for
的索引格式: “(item, index) in 数组”- 注意顺序:数组元素项item在前,索引项index在后。
-
v-for
遍历对象,支撑下面三种格式:- 一个参数: “value in object”
- 二个参数: “(value, key) in object”
- 三个参数: “(value, key, index) in object
- value 是当前项的属性值,value 是当前项的属性名,index当前项的索引
v-for也可以遍历其他可迭代对象,只要可迭代的数据类型都可以被v-for指令遍历
2.3 v-for遍历数组格式数据代码示例
<div id="app">
<!-- 1.电影列表进行渲染 -->
<h2>电影列表</h2>
<ul>
<li v-for="movie in movies">{{ movie }}</li>
</ul>
<!-- 2.电影列表同时有索引 -->
<ul>
<li v-for="(movie, index) in movies">{{index + 1}} - {{ movie }}</li>
</ul>
<!-- 3.遍历数组复杂数据 -->
<h2>商品列表</h2>
<div class="item" v-for="item in products">
<h3>商品: {{item.name}}</h3>
<span>价格: {{item.price}}</span>
<p>秒杀: {{item.desc}}</p>
</div>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
// 1.movies
movies: ["星际穿越", "少年派", "大话西游"],
// 2.数组: 存放的是对象
products: [
{ id: 110, name: "Macbook", price: 9.9, desc: " 快来抢购!" },
{ id: 111, name: "iPhone", price: 8.8, desc: "快来抢购!" },
{ id: 112, name: "小米电脑", price: 9.9, desc: " 快来抢购!" },
]
}
},
})
// 2.挂载app
app.mount("#app")
</script>
2.4 v-for遍历对象、字符串、数字格式数据代码示例
<div id="app">
<!-- 1.遍历对象 -->
<ul>
<li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li>
</ul>
<!-- 3.遍历字符串(iterable) -->
<ul>
<li v-for="item in message">{{item}}</li>
</ul>
<!-- 4.遍历数字 -->
<ul>
<li v-for="item in 100">{{item}}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
message: "Hello Vue",
info: { name: "张三", age: 18, height: 1.78 }
}
},
})
// 2.挂载app
app.mount("#app")
</script>
2.5 使用template优化多余的div
<div id="app">
<!-- 如果包裹内容的div没有实际的意义, 那么可以使用template替换 -->
<template v-for="(value, key, index) in infos">
<span>{{value}}</span>
<strong>{{key}}</strong>
<i>{{index}}</i>
</template>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
data() {
return {
info: { name: "张三", age: 18, height: 1.78 }
}
},
})
// 2.挂载app
app.mount("#app")
</script>
三、数组更新监测
3.1 能够被Vue监测到的数组更新方法
Vue
将被侦听的数组的变更方法进行了包裹,它们的使用会触发视图更新。
这些被包裹过的方法包括:
-
push() – 将一个或多个元素添加到数组的末尾,并返回该数组的新长度
-
pop() – 从数组中删除最后一个元素,并返回该元素的值
-
shift() – 从数组中删除
第一个
元素,并返回该元素的值 -
unshift() – 将一个或多个元素添加到数组的
开头
,并返回该数组的
新长度
-
splice() – 删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容
-
sort() – 对数组的元素进行排序,并返回数组
-
reverse() – 将数组中元素的位置颠倒,并返回该数组
3.2 不能够被Vue监测到的数组更新方法
不修改原数组的方法是不能被
Vue
侦听到,并且渲染到页面上的。
比如:
- filter() – 对满足条件的数据进行过滤,返回一个新数组
- concat() – 用于合并两个或多个数组,返回一个新数组
-
slice() – 按
begin
和
end
截取的原数组的
浅拷贝
(包括
begin
,不包括
end
),返回一个新数组 - map() – 按函数进行数组各项元素的转换,返回一个新数组
…
除了上面的方法外,其它不修改原数组而返回一个新数组的方法不能被
Vue
侦听到。
就看会不会修改原数组,会修改原数组的方法,就会触发视图更新。
四、v-for中的key属性
4.1 v-for中的key属性的使用示例
<div id="app">
<button @click="insertF">插入f</button>
<ul>
<!-- key要求是必须唯一 -->
<!-- 如果数据中有id可以使用id做key, 没id则使用索引 -->
<li v-for="(item, index) in letters" :key="index">{{item}}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
// 1.创建app
const app = Vue.createApp({
// data: option api
data() {
return {
letters: ["a", "b", "c", "d", "e"]
}
},
methods: {
insertF() {
this.letters.splice(2, 0, "f")
this.letters.splice()
}
}
})
// 2.挂载app
app.mount("#app")
</script>
4.2 为什么使用key属性
在使用
v-for
进行列表渲染时,我们通常会给元素或者组件绑定一个
key
属性。
这个
key
属性的官方解释:
-
key
属性主要用在
Vue
的虚拟
DOM
算法,在新旧
nodes
对比时辨识
VNodes
; -
不使用
key
,
Vue
会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法; -
使用
key
时,它会基于
key
的变化重新排列元素顺序,并且会移除/销毁
key
不存在的元素;
4.3 什么是VNode
VNode
的全称是
Virtual Node
,也就是虚拟节点。
实际上,无论是组件还是元素,它们最终在
Vue
中表示出来的都是一个个
VNode
。
但是
VNode
的本质依旧是一个
JavaScript
的对象。
在
Vue
中,
template
模板选项会先转换成
VNode
,最后再转换成浏览器上显示的真实
DOM
。
4.4 什么是虚拟Dom
如果有一大堆的元素,
Vue
会将所有元素都渲染成一个个
VNode
,形成一个
VNode Tree
。
这个
VNode Tree
就是虚拟
DOM
。
它的本质是保存
DOM
关键信息的
js
对象。
标签到虚拟
DOM
和真实
DOM
的转换过程:
为什么不直接转换成真实
DOM
,而是要借助虚拟
DOM
呢?
-
更有利于进行
diff
算法分析 -
有利于代码的跨平台。
-
虚拟
DOM
可以根据不同的平台解析成不同形式的元素,实现一份代码多平台复用。
-
虚拟
4.5 diff算法
diff
算法是一种用来比较新旧虚拟DOM的算法,用来提升程序的执行效率。
具体比较方式:
-
根元素改变 – 删除当前DOM树重新建
-
根元素未变, 属性改变 – 更新属性
-
根元素未变, 子元素/内容改变
有无key的区别:
-
无
key
– 就地更新,
Vue
底层执行
patchUnkeyedChildren
方法 -
有
key
– 按
key
比较,
Vue
底层执行
patchKeyedChildren
方法
好处:
-
在没有
key
的时候我们的效率是非常低效的 -
在进行插入或者重置顺序的时候,保持相同的
key
可以让
diff
算法更加的高效