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

相关推荐
console.log('npc')23 分钟前
[特殊字符] AI Agent 工作台前端实战教程 · 新手入门指南
前端·人工智能
gCode Teacher 格码致知26 分钟前
前端教学2:ul标签的应用场合与经典案例
前端
const_qiu1 小时前
第 2.5 章 2.5.6:前端登录、Token 无感续签与路由守卫
java·前端·人工智能·状态模式
用户83134859306981 小时前
Vue3 事件:常用用法与开发高频坑点
前端·javascript·vue.js
weixin_446260851 小时前
ReAct‑Evolve:基于轨迹反馈的ReAct智能体自主提示演化系统
前端·react.js·前端框架
其实防守也摸鱼1 小时前
存储管理:页面置换算法学习任务(测验题要求给出置换页面顺序,缺页次数,缺页率)
android·前端·数据库·学习·oracle·自动化
怒放的生命19911 小时前
前端项目 Docker 打包实操指南
前端·docker·容器
tedcloud1231 小时前
Docker Compose 部署 Immich:手机照片自动备份与常见故障排查
运维·前端·docker·容器·智能手机·开源·流程图
时间的情敌1 小时前
《WebGIS 前端的成长路线,三维可视化工程师需要掌握什么》
前端·状态模式
漫步人生走在路上1 小时前
用小语种SEO突破外贸B2B天花板:法语、德语市场的实测数据
开发语言·前端·javascript·人工智能·搜索引擎·ecmascript