部分转自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. MySQL该使用哪种CPU架构服务器?

    1. 摘要 近期,阿里云推出基于 ARM 架构的 RDS MySQL 和 RDS PostgreSQL 实例,现处于邀测阶段,阿里云宣传 ARM 架构的亮点是:在价格下降13%的基础上,平均性能 AR ...

  2. 2022春每日一题:Day 24

    题目:Work Group 树形dp,设状态f[u][0/1] 表示以u为根节点,他的子树中选了0(偶数)1(奇数)个节点的最大价值,设x为他的一个儿子,显然f[u][1]=max(f[k][0]+f ...

  3. CPU体系(1):内存模型 & CPU Cache一致性 (待整理)

    C++中的 volatile, atomic, memory barrier 应用场景对比 -- volatile memory barrier atomic 抑制编译器重排 Yes Yes Yes ...

  4. 如何使用 LinkedHashMap 实现 LRU 缓存?

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 在上一篇文章里,我们聊到了 HashMap 的实现原理和源码分析,在源码分析的过程中,我 ...

  5. 使用Typora

    Markdown学习 标题:#+空格+名称 二级标题 二级标题:##+空格+名称 三级标题 几级标题以此类推,最多支持到六级标题 字体 Hello,world! 变粗体:一句话的前后加上两个** 变斜 ...

  6. Idea中Git的常用操作及可能存在的问题

    一.使用 1.从git上下载项目 (1)默认branch下载(pull) (2)指定branch下载 (3)克隆远程仓库到本地(git clone) git clone https://github. ...

  7. SpringMVC02:返回值、json数据、文件上传、拦截器

     一.响应返回值 1.搭建环境(两个webapp,不要选错) 2.响应之返回值是String类型 package cn.itcast.controller; import cn.itcast.doma ...

  8. Pointers and Constants

    Pointers and Constants char * const q = "abc"; // q is const *q = 'c'; // OK q++; //ERROR ...

  9. 痞子衡嵌入式:存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是存储器大厂Micron的NOR Flash芯片特殊丝印设计(FBGA代码). 痞子衡之前写过一篇文章 <J-Flash在Micron ...

  10. CCS选择器 选择器优先级 选择器常见属性

    目录 CSS前戏 1.css语法结构 2.css注释语法 3.引入css的多种方式 CSS基本选择器 1.标签选择器 2.类选择器 3.id选择器 4.通用选择器 CSS组合选择器 1.后代选择器(空 ...