部分转自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的作用及原理的更多相关文章

  1. v-for中key的作用与原理

    一.虚拟DOM中key的作用 key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue会对新虚拟DOM与旧虚拟DOM的差异进行比较. 二.如何选择key 最好使 ...

  2. (转)Vue种key的作用

    https://blog.csdn.net/qq_41861679/article/details/80659278 https://cn.vuejs.org/v2/api/#key 其实不只是vue ...

  3. vue中key的作用 v-for里警告 v-if的复用

    vue总是会复用页面上已经存在的dom,区别的方法是加上key就可以,还设有v-for时候的警告也是如此key的作用是区别这条跟那条的.<body> <div id="ap ...

  4. 图解vue中 v-for 的 :key 的作用,虚拟dom Diff算法

    其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性. 要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了. 我们知道,vue和react都实现了一套虚拟D ...

  5. react key的作用

    react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的(例如你为一个组件设置key之后不能获取组件的这个key props),而是给react自己用的. 简单来说,react利用key ...

  6. Vue中使用key的作用

    key的作用是为了在diff算法执行时更快的找到对应的节点,提高diff速度 key具有唯一性 vue中循环需加 :key=“唯一标识” ,唯一标识可以使item里面id index 等,因为vue组 ...

  7. vue key的作用

    key的作用是什么? 简单来说: key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点. 1. 更准确 因为带key就不是就地复用了,在sa ...

  8. v-for中的key的使用【key的作用主要是是为了高效的更新虚拟DOM】

    vue中列表循环需加:key="唯一标识" 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用 ...

  9. vue中:key 和react 中key={} 的作用,以及ref的特性?

    vue中:key 和react 中key={} 为了给 vue 或者react 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性 一句话概括就是 ...

  10. ON DUPLICATE KEY UPDATE作用

    ON DUPLICATE KEY UPDATE作用 先声明一点,ON DUPLICATE KEY UPDATE为Mysql特有语法,这是个坑 语句的作用,当insert已经存在的记录时,执行Updat ...

随机推荐

  1. Xtrabackup使用帮助

    目录 1.安装工具 2.下载后上传到需要备份的服务器 全备 1.安装完成后我们进行数据库备份执行以下命令 2.查看备份的数据 3.进入数据库,删除一个测试库 4.删除school库 5.备份数据目录 ...

  2. 面试 考察js基础不能不会的内容(第五天)

    01.描述事件冒泡的流程 基于 DOM 树结构,事件会顺着触发元素向上冒泡 点击一个div,会一级一级向父级.爷级元素上冒泡,这个点击事件不仅能被这个div捕捉到,也能被他的父级.爷爷级-元素捕捉到 ...

  3. C++ using 编译指令与名称冲突

    using 编译指令:它由名称空间名和它前面的关键字 using namespace 组成,它使名称空间中的所有名称都可用,而不需要使用作用域解析运算符.在全局声明区域中使用 using 编译指令,将 ...

  4. UBOOT编译--- UBOOT的$(version_h) $(timestamp_h)(七)

    1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概述 在编译uboot的过程中,有两个特别的依赖version_h 和 timestamp_h,它们定义 ...

  5. RabbitMq了解

    RibbitMQ MQ优势 MQ的三大主要作用: 应用解耦.异步提速.流量削锋 应用解耦 系统的耦合性越高,容错性就越低,可维护性就越低: 解耦: 如果其中一个系统服务宕机,那么系统的其他服务将也无法 ...

  6. js 获取相同name元素的属性值

    如图有8-12月5个文本域,id为plan8-12,name同为plan. 现在要获取name同为plan的所有属性值: 方法一: var allplan =document.getElementsB ...

  7. vulnhub靶场之HACKSUDO: THOR

    准备: 攻击机:虚拟机kali.本机win10. 靶机:hacksudo: Thor,下载地址:https://download.vulnhub.com/hacksudo/hacksudo---Tho ...

  8. 写一个flutter程序

    这一部分我们写一个简单应用 功能是,为一个创业公司生成建议的公司名称. 用户可以选择和取消选择的名称,保存喜欢的名称. 该代码一次生成十个名称 用户滚动时,生成新一批名称. 着重体验以下几点 Flut ...

  9. 【每日一题】【map操作】【滑动窗口所需元素】2021年12月22日-76. 最小覆盖子串

    给你一个字符串 s .一个字符串 t .返回 s 中涵盖 t 所有字符的最小子串.如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" . 注意: 对于 t 中重复字符 ...

  10. 乐观锁思想在JAVA中的实现——CAS

    更多技术干活尽在个人公众号--JAVA旭阳 前言 生活中我们看待一个事物总有不同的态度,比如半瓶水,悲观的人会觉得只有半瓶水了,而乐观的人则会认为还有半瓶水呢.很多技术思想往往源于生活,因此在多个线程 ...