vue的v-for循环key属性为什么不能用index?

html 复制代码
const list = ref([
    {
      id:1,
      text:"aaa"
    },{
      id:2,
      text:"bbb"
    },{
      id:3,
      text:"ccc"
    }
])
html 复制代码
  <ul>    <li v-for="(item, index) in list"  >{{ item.text }}</li>  </ul>

以上代码运行后,渲染出来是这样的:

然后我们给list的末尾加一个新元素:

php 复制代码
  list.value.push({      id:100,      text:"ddd"  })

加上新元素后,页面展示如下

其实一开始,是有一个虚拟dom列表的,list增加新元素后,又会生成一个新的虚拟dom列表

新旧虚拟dom列表如下,左边的旧的,右边是新的

创建新虚拟dom列表后,与旧的虚拟dom比较,上图种,左边第0个与右边第0个是一样的,所以真实dom里的第0个li不变,

左边第1个与右边第1个是一样的,所以真实dom里的第1个li不变,

左边第2个与右边第2个是一样的,所以真实dom里的第2个li不变

右边有第三个,左边没有第三个,所以会在真实dom列表里新创建一个dom,里面显示ddd

接下来,看看另一种案例:

php 复制代码
const list = ref([    {      id:1,      text:"aaa"    },{      id:2,      text:"bbb"    },{      id:3,      text:"ccc"    }])
xml 复制代码
  <ul>    <li v-for="(item, index) in list"  >{{ item.text }}</li>  </ul>

运行后页面如下:

然后,我们在list的index为1的位置插入一个新元素

php 复制代码
  list.value.splice(1, 0 ,{      id:100,      text:"ddd"  })

然后页面显示如下:

往list里插入新元素后,新旧虚拟dom列表可以表示如下

然后vue会比较新旧列表

左边第0个与右边第0个是一样的,所以真实dom里的第0个li不变,

左边第1个与右边第1个不一样,所以真实dom里的第1个li会被修改,

左边第2个与右边第2个不一样,所以真实dom里的第2个li会被修改,

右边有第三个,左边没有第三个,所以会在真实dom列表里新创建一个dom,里面显示ccc

我们可以看到,往list里插入新元素后,真实dom里的第1个到第二个li都更新了,这样性能太差了

接下来,再写一个案例,给v-for加key


php 复制代码
const list = ref([    {      id:1,      text:"aaa"    },{      id:2,      text:"bbb"    },{      id:3,      text:"ccc"    }])
css 复制代码
  <ul>    <li v-for="(item, index) in list" :key="item.id" >{{ item.text }}</li>  </ul>

注意,这里我给li加了个key属性,值为item.id

运行后页面是这样的:

然后,我们在list的index为1的位置插入一个新元素

php 复制代码
  list.value.splice(1, 0 ,{      id:100,      text:"ddd"  })

然后页面显示如下:

新虚拟dom列表和旧虚拟dom列表可以表示如下:

这次,他们是有key属性的,在有key属性的情况下,新旧虚拟dom的比较过程是这样的:

key为0的旧虚拟dom和key为0的新虚拟dom一样,

key为1的旧虚拟dom和key为1的新虚拟dom一样,

key为2的旧虚拟dom和key为2的新虚拟dom一样

所以真实dom里的这三个li不会改变

新的虚拟dom列表里多了一个key为100的虚拟dom,并且在索引为1的位置

所以vue会在真实的dom里,索引为1的地方插入一个新的li,li里的内容是ddd

看到没,这次不像上一个案例里那样改变了2个li,这次只要增加一个li,原来的三个li完全不用改变,性能是不是比较好了

用index作为key

接下来,说说如果用index来作为key,会怎么样

php 复制代码
const list = ref([    {      id:1,      text:"aaa"    },{      id:2,      text:"bbb"    },{      id:3,      text:"ccc"    }])
css 复制代码
  <ul>    <li v-for="(item, index) in list" :key="index" >{{ item.text }}</li>  </ul>

运行后页面是这样的:

然后,我们在list的index为1的位置插入一个新元素

php 复制代码
  list.value.splice(1, 0 ,{      id:100,      text:"ddd"  })

然后页面显示如下:

新虚拟dom列表和旧虚拟dom列表可以表示如下:

他们是有key属性的,在有key属性的情况下,新旧虚拟dom的比较过程是这样的:

key为0的旧虚拟dom和key为0的新虚拟dom一样,所以真实dom里的第0个li不用改变

key为1的旧虚拟dom和key为1的新虚拟dom不一样,所以真实dom里的第1个li要改变

key为2的旧虚拟dom和key为2的新虚拟dom不一样,所以真实dom里的第2个li要改变

新的虚拟dom列表末尾多了一个key为3的虚拟dom,所以在真实li列表末尾创建一个新的li

你看,这样bbb和ccc这两个li都需要被改变,跟上一个案例比较一下,这次改变的真实dom比较多,所以不能用index来作为key的值

相关推荐
汉得数字平台7 分钟前
【鲲苍提效】全面洞察用户体验,助力打造高性能前端应用
前端·前端监控
花海如潮淹14 分钟前
前端性能追踪工具:用户体验的毫秒战争
前端·笔记·ux
_丿丨丨_5 小时前
XSS(跨站脚本攻击)
前端·网络·xss
天天进步20155 小时前
前端安全指南:防御XSS与CSRF攻击
前端·安全·xss
拾光拾趣录8 小时前
括号生成算法
前端·算法
拾光拾趣录8 小时前
requestIdleCallback:让你的网页如丝般顺滑
前端·性能优化
前端 贾公子8 小时前
vue-cli 模式下安装 uni-ui
前端·javascript·windows
拾光拾趣录9 小时前
链表合并:双指针与递归
前端·javascript·算法
@大迁世界9 小时前
前端:优秀架构的坟墓
前端·架构
期待のcode9 小时前
图片上传实现
java·前端·javascript·数据库·servlet·交互