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的值

相关推荐
计算机魔术师4 分钟前
AI 写了一半代码,谁来背锅?Anthropic 的安全重构笔记
前端
明月_清风21 分钟前
vLLM 深度实战:2026 年生产级 LLM 推理引擎完全指南
前端·后端·ai编程
风月说与山鬼22 分钟前
七、uni-app页面与组件生命周期
前端·uni-app
绿岛之北27 分钟前
Electron 安全第三章:URL 加载与 WebView
前端·electron
sunoo-22928 分钟前
C 语言文件 IO 全攻略:从基础函数到实战踩坑(BMP 读取 + 词典查询)
linux·c语言·前端·笔记·vscode·学习
Shinner欣儿29 分钟前
React18 并发渲染小记
前端
用户9210802628638 分钟前
AI 对话里的消息时间线分页:上滑加载更多历史记忆的实现与坑点
前端
PedroQue9941 分钟前
Vue-Router 2.4.0 新增可控重定向功能
前端·uni-app
阿萨德528号1 小时前
npm 包发布实战指南:从零发布、更新迭代到版本治理
前端·npm·策略模式
IT_陈寒1 小时前
Vue的v-for为啥把我的渲染顺序搞乱套了?
前端·人工智能·后端