vue中使用v-for时为什么不能用index作为key


Posted in Javascript onApril 04, 2020

结论:

  • 更新DOM的时候会出现性能问题
  • 会发生一些状态bug
  • React 中的 key 也是如此
  • 如果已经了解 为什么要用key,可以通过目录直接跳到下一节。

为什么要用key?

Vue 和 React 都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。

Vue 和 React 的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:

  1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
  2. 同一层级的一组节点,他们可以通过唯一的id进行区分。

基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。

用一张图简单说明一下:

vue中使用v-for时为什么不能用index作为key

当页面的数据发生变化时,Diff算法只会比较同一层级的节点:

如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点。

如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。

举个栗子:

vue中使用v-for时为什么不能用index作为key

我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:

vue中使用v-for时为什么不能用index作为key

即把C更新成F,D更新成C,E更新成D,最后再插入E,这样效率不高,且性能不够好。

但是,如果使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

vue中使用v-for时为什么不能用index作为key

总而言之,key的作用主要是为了高效的更新虚拟DOM 。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

这里,也建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单。

为什么不能用index作为key?

举个栗子:

<template>
  <div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
</template>
const list = [
  {
    id: 1,
    name: "Person1"
  },
  {
    id: 2,
    name: "Person2"
  },
  {
    id: 3,
    name: "Person3"
  },
  {
    id:4,
    name:"Person4"
  }
];

此时,删除 “Person4” 是正常的,但是如果我删除 “Person2” 就会出现问题。

删除前

key id index name
0 1 0 Person1
1 2 1 Person2
2 3 2 Person3
3 4 3 Person4

删除后

key id index name
0 1 0 Person1
1 3 1 Person3
2 4 2 Person4

这个时候,除了 Person1 之外,剩下的 Person3、Person4,因为被发现与相应 key 的绑定关系有变化,所以被重新渲染,这会影响性能。
如果此时 list 的 item 是 select 的选项,其中 Person3 是选中的,这个时候 Person2 被删除了,用 index 作为 key 就会变成是 Person4 选中的了,这就产生了bug。

如果使用唯一id作为key,删除 Person2 后,剩下的元素因为与 key 的关系没有发生变化,都不会被重新渲染,从而达到提升性能的目的。此时,list 的 item 作为 select 的选项,也不会出现上面所描述的bug。

到此这篇关于vue中使用v-for时为什么不能用index作为key的文章就介绍到这了,更多相关vue v-for不能用index作为key内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
document对象execCommand的command参数介绍
Aug 01 Javascript
jquery 常用操作整理 基础入门篇
Oct 14 Javascript
Firebug 字幕文件JSON地址获取代码
Oct 28 Javascript
ASP.NET jQuery 实例2 (表单中使用回车在TextBox之间向下移动)
Jan 13 Javascript
JS格式化数字金额用逗号隔开保留两位小数
Oct 18 Javascript
使用jQuery Rotare实现微信大转盘抽奖功能
Jun 20 Javascript
js利用正则表达式检验输入内容是否为网址
Jul 05 Javascript
javascript中href和replace的比较(详解)
Nov 25 Javascript
微信小程序实战之运维小项目
Jan 17 Javascript
ionic grid(栅格)九宫格制作详解
Jun 30 Javascript
vue router 组件的高级应用实例代码
Apr 08 Javascript
Vue $mount实战之实现消息弹窗组件
Apr 22 Javascript
详解为什么Vue中不要用index作为key(diff算法)
Apr 04 #Javascript
原理深度解析Vue的响应式更新比React快
Apr 04 #Javascript
Vue的data、computed、watch源码浅谈
Apr 04 #Javascript
VUE table表格动态添加一列数据,新增的这些数据不可以编辑(v-model绑定的数据不能实时更新)
Apr 03 #Javascript
mpvue实现微信小程序快递单号查询代码
Apr 03 #Javascript
mpvue网易云短信接口实现小程序短信登录的示例代码
Apr 03 #Javascript
javascript用defineProperty实现简单的双向绑定方法
Apr 03 #Javascript
You might like
谈谈PHP的输入输出流
2007/02/14 PHP
PHP下用rmdir实现删除目录的三种方法小结
2008/04/20 PHP
php遍历解析xml字符串的方法
2016/05/05 PHP
jquery实现带二级菜单的导航示例
2014/04/28 Javascript
JavaScript对象之深度克隆介绍
2014/12/08 Javascript
JavaScript中的对象序列化介绍
2014/12/30 Javascript
jquery实现相册一下滑动两次的方法
2015/02/09 Javascript
jQuery检测输入的字符串包含的中英文的数量
2015/04/17 Javascript
自定义刻度jQuery进度条及插件
2015/09/02 Javascript
jquery实现鼠标悬浮停止轮播特效
2020/08/20 Javascript
理解javascript中的MVC模式
2016/01/28 Javascript
Easyui Treegrid改变默认图标的方法
2016/04/29 Javascript
vue2.0开发入门笔记之.vue文件的生成和使用
2017/09/19 Javascript
微信小程序仿抖音视频之整屏上下切换功能的实现代码
2020/05/24 Javascript
Vue中keep-alive的两种应用方式
2020/07/15 Javascript
在antd中setFieldsValue和defaultVal的用法
2020/10/29 Javascript
vue项目中企业微信使用js-sdk时config和agentConfig配置方式详解
2020/12/15 Vue.js
Vue使用Ref跨层级获取组件的步骤
2021/01/25 Vue.js
[02:09]2018DOTA2亚洲邀请赛TNC赛前采访
2018/04/04 DOTA
python网页请求urllib2模块简单封装代码
2014/02/07 Python
python 远程统计文件代码分享
2015/05/14 Python
Python常见加密模块用法分析【MD5,sha,crypt模块】
2017/05/24 Python
Python之使用adb shell命令启动应用的方法详解
2019/01/07 Python
python 通过类中一个方法获取另一个方法变量的实例
2019/01/22 Python
基于PyQt4和PySide实现输入对话框效果
2019/02/27 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
Python ArgumentParse的subparser用法说明
2020/04/20 Python
使用CSS3实现多列布局与多背景的技巧
2016/02/29 HTML / CSS
YOOX美国官方网站:全球著名的多品牌时尚网络概念店
2016/09/11 全球购物
什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?
2016/08/13 面试题
2014年中班元旦活动方案
2014/02/14 职场文书
2014年驾驶员工作总结
2014/11/18 职场文书
会计专业求职信范文
2015/03/19 职场文书
岁月神偷观后感
2015/06/11 职场文书
CSS 使用 resize 实现图片拖拽切换预览功能(强大功能)
2021/08/23 HTML / CSS
Python Matplotlib绘制动画的代码详解
2022/05/30 Python