一、v-for列表渲染
在真实开发中,我们往往会从服务器拿到一组数据,并且需要对其进行渲染。
- 这个时候我们可以使用v-for来完成;
- v-for类似于JavaScript的for循环,可以用于遍历一组数据;
二、v-for基本使用
(1)遍历数组
我们直接上demo~
<!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">
<!-- 1. 遍历数组 -->
<!-- 2. 遍历对象 -->
<ul>
<!-- 2.1 一个参数 -->
<li v-for="value in info">{{value}}</li>
</ul>
<ul>
<!-- 2.2 两个参数 -->
<li v-for="(value, key) in info">{{value}} - {{key}}</li>
</ul>
<ul>
<!-- 2.3 三个参数 -->
<li v-for="(value, key, index) in info">{{value}} - {{key}} - {{index}}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
message: "Hello Vue",
movies: [],
info: { name: "daxia", age: 18, height: 1.88 },
}
},
})
app.mount("#app")
</script>
</body>
</html>
(2) 遍历对象
<!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">
<!-- 1. 遍历数组 -->
<!-- 2. 遍历对象 -->
<ul>
<!-- 2.1 一个参数 -->
<li v-for="value in info">{{value}}</li>
</ul>
<ul>
<!-- 2.2 两个参数 -->
<li v-for="(value, key) in info">{{value}} - {{key}}</li>
</ul>
<ul>
<!-- 2.3 三个参数 -->
<li v-for="(value, key, index) in info">{{value}} - {{key}} - {{index}}</li>
</ul>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
message: "Hello Vue",
movies: [],
info: { name: "daxia", age: 18, height: 1.88 },
}
},
})
app.mount("#app")
</script>
</body>
</html>
(3)遍历字符串
(4)遍历数字
三、数组更新检测
我们上代码~
<!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>
<button @click="changeArray">修改数组</button>
</div>
<script src="../lib/vue.js"></script>
<script>
const app = Vue.createApp({
// data: option api
data() {
return {
names: ["abc", "cba", "nba", "aaa", "ccc"],
}
},
methods: {
changeArray() {
// 1. 直接将数组修改为一个新的数组
// this.names = ["why", "kobe"]
// 2. 通过一些数组的方法,修改数组中的元素
// this.names.push("why")
// this.names.pop()
// 索引,删除元素的个数(添加的话就是写0),
// this.names.splice(2, 1, "why")
// 排序
// this.names.sort()
// 反转
this.names.reverse()
},
},
})
app.mount("#app")
</script>
</body>
</html>
注意:不修改原数组的方法是不能侦听(watch)
// 3. 不修改原数组的方法是不能侦听(watch)
const newNames = this.names.map((item) => item + "why")
this.names = newNames
四、v-for的key属性
(1) 认识VNode
我们先来解释一下VNode的概念:
- 因为目前我们还没有比较完整的学习组件的概念,所以目前我们先理解HTML元素创建出来的VNode。
- VNode的全称是Virtual Node,也就是虚拟节点;
- 事实上,无论是组件还是元素,它们最终在Vue中表示出来的都是一个个VNode;
- VNode的本质是一个JavaScript的对象;
我们先来理解一下,现在id=app的div元素,是不是相当于模板,以前我们是写在下面的,现在写在了上面。
vue并不会根据你写的h2,直接去给你创建一个h2元素。如果直接给你#app.append(h2元素),追加了h2元素的话, 那此时不就是真实DOM的h2元素。
他会在生成真实DOM的h2元素之前,先生成一个VNode。
那VNode到底是一个什么东西呢?
答:VNode的本质是一个JavaScript的对象。他直接用一个JavaScript对象把他表现出来了,并没有直接给你表现出一个h2元素。
假如说你的模板里面有个div元素,他会先把你这个div元素先做一个解析(源码里其实有专门的一部分代码来解析下面这个div元素的,解析成VNode),解析成啥样子的?就是下方的图。本质上就是一个java Script对象。
我们有了VNode,有直接转化成我们真实DOM里面的元素吗? 答:目前还没有。
当我们有了VNode之后,我们就可以对这个Vnode进行解析了。原来我们创建的元素是div元素,原来我们创建的元素的属性是...等等。最终的话再由我们的VNode转换成真实DOM里面的元素,转换成真实DOM里面的元素之后,我们才能在这是DOM里面看到该元素,在 用户界面才能看到。(先做一个了解,后面看源码)。
(2) 虚拟DOM
有童鞋好奇,为什么非要中间加一个虚拟节点、虚拟DOM这个概念,直接创建真实DOM不好吗?
这里最主要的原因有2个:
1. 如果我们当前有个虚拟DOM,方便他去做diff算法。(在下面第六点会提到)
2. 如果有了虚拟DOM,他方便对我们的代码进行跨平台。
我们可以通过虚拟DOM转换成真实DOM,并且渲染到浏览器上面
我们也可以通过虚拟DOM,解析这个java Script对象结构变成移动端的button/view/image等类似控件,然后渲染到移动端显示出来。
我们还可以通过虚拟DOM渲染到桌面端一些控件。
我们也可以渲染到VR设备。
(3)v-for的key属性的作用
了解了VNode、虚拟DOM和真实DOM的概念之后,我们再来看下v-for的key的属性的作用。
我们来个demo,我们想要在letters里面b和c之间插入一个f怎么做?
如果我们未插入一个f之前,我们已经有了虚拟DOM,然后通过原先的虚拟DOM创建了一个真实DOM。
这个时候我们由中间某一个位置给他插入一个东西的时候,我们思考下有几种做法?
1. 第一种,原来这些节点全部不要了, 我从a开始重新创建一个个节点,然后渲染成真实DOM。(没有必要这么去做,为什么?因为刚才的a节点,b节点没有发生变化。没有必要全部销毁从0开始)
2. 第二种, a b 保留,f替代原来c的位置,后面的都得修改。后面少一个了,就去新建e节点。
这种算法的效率不高,因为这里有很多c后面开始重新需要修改的。(他并不知道上面这个c和下面的这个c可以重复利用。)这就是vue没有设置key的情况下的算法。仅在中间插入的时候是这样子,如果是在最后插入的话,是没什么区别的。
3. 第三种, 跟上面第二种的区别就是,我给每一个节点加个key。这样子第二次虚拟DOM的时候,我就能知道第一次虚拟DOM的c,d,e,都是可以重复利用的。
总结:所以 v-for 加key属性的作用就是让vue更快识别出来 两个节点是同一个东西。
没有key的diff算法:
有key的diff算法: