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

相关推荐
IT女孩儿18 分钟前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡1 小时前
commitlint校验git提交信息
前端
虾球xz2 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇2 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒2 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员2 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐2 小时前
前端图像处理(一)
前端
程序猿阿伟2 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒2 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪3 小时前
AJAX的基本使用
前端·javascript·ajax