Vue15 v-for和key的作用及原理
部分转自https://blog.csdn.net/cun_king/article/details/120714227
1 v-for指令
1.1 简介
用于遍历。
当在组件中使用 v-for 时,key 现在是必须的。它需要一个唯一id
1.2 遍历数组
<template>
<p v-for="(item,index) in list" :key="index">索引{{index}}----{{item}}</p>
</template> <script>
export default {
data () {
return {
list:[1,2,3],
}
},
}
</script>
1.3 遍历对象数组
<template>
<p v-for="(item,index) in list" :key="index">索引{{index}}--{{item.name}}--{{item.money}}</p>
</template> <script>
export default {
data () {
return {
list:[
{ "name": "小米手机", "money": 100 },
{ "name": "华为手机", "money": 200 },
{ "name": "苹果手机", "money": 300 },
{ "name": "魅族手机", "money": 400 }
],
}
},
}
</script>
1.4 遍历对象
<template>
<!-- 注意:在遍历对象身上的键值对的时候, 除了 有 val key ,在第三个位置还有 一个 索引 -->
<p v-for="(val, key, i) in list">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p> </template> <script>
export default {
data () {
return {
list:{
id: 1,
name: '小明',
gender: '男'
},
}
},
}
</script>
1.5 遍历字符串
<body> <div id="root"> <ul>
<li v-for="(value,index) of name">
{{value}}:{{index}}
</li>
</ul> </div> <script type="text/javascript" > const vm = new Vue({
el:'#root',
data:{
name:'杭州历史', }
}) </script>
</body>
2 key属性
2.1 简介
key在Vue是DOM对象的标识;
进行v-for列表展示时,不指定key,默认key是index;
如果数据只做展示使用,使用index作为key是没有任何问题的;
如果使用index作为key,而后续操作会破坏顺序,一定会带来效率问题,严重时会渲染出错误的DOM
2.2 key的作用
key就是一个标识,被使用在Vue中。再详细一点,key被使用在Vue中的虚拟DOM中,并不会出现在真实DOM中
2.3 仅展示列表时使用不同的key
2.3.1 示例1-不设置key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>key的原理</title> <!--引入vue-->
<script type="text/javascript" src="../js/vue.js"></script> </head>
<div id="root">
<h2>人员列表</h2>
<ul>
<li v-for="(p,index) in persons">
{{p.name}}-{{p.age}}
</li>
</ul>
</div>
<body>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
persons:[
{'id':'001', 'name':'张三','age':'18'},
{'id':'002', 'name':'李四','age':'19'},
{'id':'003', 'name':'王五','age':'20'}
]
}
})
</script>
</body>
</html>
上述示例html文件中并没有使用到key,似乎也没有问题。当然,单纯地展示数据,不写key是不会存在问题的。
2.3.2 设置id为key
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li>
页面展示结果和上图结果一模一样
而如果我们在浏览器上查看元素,li上面也不会看到key属性的存在
2.3.3 设置index为key
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
页面效果也是一样的
截至目前,我们可以得到两个结论:
2.3.4 小结
1) 只做数据展示用,不写key是没有任何影响的;
2)key不会出现在真实DOM中
3)实际上,即使不写key,Vue在生成真实DOM时,也用到了key,默认是数据索引(index)
2.4 不仅仅是展示的时候
在展示人员信息的基础上显示索引,并且添加一个按钮,功能是在头部添加人员信息
2.4.1 示例 index作为key
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>key的原理</title> <!--引入vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<link rel="icon" href="../favicon.ico" type="image/x-icon" /> </head>
<div id="root">
<h2>人员列表</h2>
<button @click="add">添加一个老刘</button>
<ul>
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
</div>
<body>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
persons:[
{'id':'001', 'name':'张三','age':'18'},
{'id':'002', 'name':'李四','age':'19'},
{'id':'003', 'name':'王五','age':'20'}
]
},
methods:{
add(){
const p = {'id':'004', 'name':'老刘','age':'40'}
this.persons.unshift(p)
}
}
})
</script>
</body>
</html>
点击按钮,添加一个新人物,这个时候索引发生了变化,新添加的人物“老刘”变为了索引0。
也就是说,使用index作为key,那么元素的index是可能会变化的
2.4.2 示例 index作为key
不展示索引了,改为输入框,在每个人物后面的输入框内写上人物的姓,观察新插入数据后原始数据的变化
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
</li>
在输入框中输入内容,效果如上图所示,似乎没有什么不对,接下来就是见证奇迹的时刻
添加老刘,出现了问题,和我们预想的不一样。如下图,输入框和姓名对不上了。
2.4.3 id作为key
如果修改为数据的唯一标识,则不会产生这样的问题
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
<input type="text">
</li>
如下图,添加老刘后,名字和输入框还是对应的
3 key的原理
那么为什么使用index作为key会出现上面的问题的,二使用id就不会呢?
3.1 虚拟dom
要解释key的实现原理,就要引入Vue一个十分重要的概念——虚拟DOM。
给出一组数据和模板,Vue要把这些数据渲染到页面上,首先要生成虚拟DOM,然后根据虚拟DOM去生成真实的DOM,真实的dom就是页面上显示的。如果数据发生了改变,Vue会生成新的虚拟DOM,然后再去生成新的真实DOM,关键就是这个新的真实DOM的生成方式了。
并不是直接通过新的虚拟DOM生成新的真实DOM,否则虚拟DOM一点用处也没有了。Vue的操作是,拿新的虚拟DOM与之前的旧的虚拟的DOM去做比较,这个比较通过key来对应的,会把key相同的新旧虚拟DOM进行比较。如果相同,直接延用之前虚拟dom生成的真实dom即可,如果不同,则生成新的真实DOM对象。
3.2 过程分析
3.2.1 key为index的情况
根据数据生成真实DOM的流程如下:(注意,下图的真实DOM中输入框里的内容为生成页面后手动添加)
然后,添加人物“老刘”,获取到一组新数据
Vue拿新数据生成新的虚拟DOM,注意,由于老刘放到了数组最前面,所以数组里面的数据的index发生了变化
在生成真实DOM时,就需要用新生成的虚拟DOM和原来的虚拟DOM作比较(一条一条分析)
对比第一条,key为0,找到旧DOM中key为0的数据,发现“老刘-40”和“张三-18”不同,创建新的真实DOM;再往后,发现输入框一致(注意,比较的是虚拟DOM,输入框里面是没有输入的文字的,所以是一致的),不必重新渲染,直接使用原来真实DOM的内容。第一条内容就出现了,而这个输入框还携带有张三的姓
对比第二条,key为1,找到旧DOM中key为1的数据,发现“张三-18”和“李四-19”不同,创建新的真实DOM;再往后,发现输入框一致,不必重新渲染,直接使用原来真实DOM的内容。第二条内容就出现了,而这个输入框还携带有李四的姓
之后同理
回顾这个过程,key是作为虚拟DOM中对象的唯一标识,标识出了数据的“身份信息”,Vue在虚拟DOM中会根据这个“身份标识”去对比内容,设计的初衷是为了节省资源开支,不必渲染重复的部分。在本示例中,不但带来了效率问题,还渲染出了错误的DOM,后果非常严重
3.2.2 key为id的情况
直接进入添加“老刘”后的新旧DOM对比
对比第一条,key为‘004’,发现在旧DOM中并不存在,直接生成新的真实的DOM。
对比第二条,key为‘001’,发现旧DOM中key为‘001’的数据相同,直接将原来的真实的DOM拿过来使用。
……
最后生成正确的DOM,节省了资源开支
Vue15 v-for和key的作用及原理的更多相关文章
- v-for中key的作用与原理
一.虚拟DOM中key的作用 key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue会对新虚拟DOM与旧虚拟DOM的差异进行比较. 二.如何选择key 最好使 ...
- (转)Vue种key的作用
https://blog.csdn.net/qq_41861679/article/details/80659278 https://cn.vuejs.org/v2/api/#key 其实不只是vue ...
- vue中key的作用 v-for里警告 v-if的复用
vue总是会复用页面上已经存在的dom,区别的方法是加上key就可以,还设有v-for时候的警告也是如此key的作用是区别这条跟那条的.<body> <div id="ap ...
- 图解vue中 v-for 的 :key 的作用,虚拟dom Diff算法
其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性. 要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了. 我们知道,vue和react都实现了一套虚拟D ...
- react key的作用
react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的(例如你为一个组件设置key之后不能获取组件的这个key props),而是给react自己用的. 简单来说,react利用key ...
- Vue中使用key的作用
key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度 key具有唯一性 vue中循环需加 :key=“唯一标识” ,唯一标识可以使item里面id index 等,因为vue组 ...
- vue key的作用
key的作用是什么? 简单来说: key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点. 1. 更准确 因为带key就不是就地复用了,在sa ...
- v-for中的key的使用【key的作用主要是是为了高效的更新虚拟DOM】
vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用 ...
- vue中:key 和react 中key={} 的作用,以及ref的特性?
vue中:key 和react 中key={} 为了给 vue 或者react 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性 一句话概括就是 ...
- ON DUPLICATE KEY UPDATE作用
ON DUPLICATE KEY UPDATE作用 先声明一点,ON DUPLICATE KEY UPDATE为Mysql特有语法,这是个坑 语句的作用,当insert已经存在的记录时,执行Updat ...
随机推荐
- 将C#的bitmap格式转换为Halcon的图像格式
/// <summary> /// Bitmap转HObject灰度图 /// </summary> /// <param name="bmp"> ...
- uboot引导应用程序
uboot默认是支持执行应用程序的,就像引导内核一样,我们也可以自己写一个应用程序,让uboot启动时引导. 在uboot examples/standalone 目录下,有hello_world.c ...
- 笔试面试--Java基础知识
一.基本概念 1.Java的优点 纯面向对象 平台无关性,"一次编译,到处运行(JVM上)",跨平台,可移植性 丰富类库:多线程.网络通信.垃圾回收 安全性(数组边界检测.byte ...
- PyQt4编写界面的两种方式
PyQt4编写界面的两种方式 应用PyQt4开发图形化界面有两种方式,一种是直接通过QtDesigner通过提供的窗口部件拖拽进行GUI创建,另外一种是直接进行编程实现. 第一种,QtDesigner ...
- 错误:org.springframework.beans.factory.BeanDefinitionStoreException:
在练习尚硅谷雷丰阳老师的SSM-CRUD整合的时候,因为使用的Thymeleaf,而不是jsp,跟着老师操作所有会出现一些错误,现在我把这些错误都整理一下,希望能帮助到有用的朋友. org.sprin ...
- CBV如何添加装饰器?
目录 一:CBV如何添加装饰器 1.CBV中django不建议直接给类的方法加装饰器 2.CBC添加装饰器的三种方法 3.CBV添加装饰器实战 一:CBV如何添加装饰器 1.CBV中django不建议 ...
- Go语言性能剖析利器--pprof实战
作者:耿宗杰 前言 关于pprof的文章在网上已是汗牛充栋,却是千篇一律的命令介绍,鲜有真正实操的,本文将参考Go社区资料,结合自己的经验,实战Go程序的性能分析与优化过程. 优化思路 首先说一下性能 ...
- Pytorch框架详解之一
Pytorch基础操作 numpy基础操作 定义数组(一维与多维) 寻找最大值 维度上升与维度下降 数组计算 矩阵reshape 矩阵维度转换 代码实现 import numpy as np a = ...
- ob-myfreemp3
网站 aHR0cDovL3Rvb2wubGl1bWluZ3llLmNuL211c2ljLw== 打开之后随便搜一个歌手的名字或歌曲(这里搜林俊杰) m/api/search,可以看到数据全在这里 全 ...
- 【Java技术专题】「原理专题」深入分析Java中finalize方法的作用和底层原理
finalize方法是什么 finalize方法是Object的protected方法,Object的子类们可以覆盖该方法以实现资源清理工作,GC在首次回收对象之前调用该方法. finalize方法与 ...