vue中使用v-for时,key值为什么不推荐使用index?

www.jswusn.com Other 2025-07-08 09:52:33 8次浏览


在进入正题之前,我们先思考一下v-for循环为什么要使用key?


key主要用来做DOM diff算法用的。diff算法就是比较两棵树(旧的虚拟 DOM 树和新的虚拟 DOM 树)之间的差异。


v-for循环加key值的必要性 


vue中如果没有显式地提供一个 key 属性,Vue 会默认使用列表项的索引作为该项的 key 值。所以给key提供index值和不给其设置key值效果一样。


列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素。


比如我们只想插入一个F,其它都不变,本应该如下图:

9277e6be9ed55c700845b8f89a0d83a6.jpg

而如果按照下图去渲染,各个位置都重新渲染一遍,就有点劳师动众了:

d5e535e2e5c90282fe607a7bea6820ec.jpg

所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

4c131754de3ab03ff48be8300ede15bc.jpg

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



案例说明v-for中key值不能是index 


选中第一个节点的复选框,点击删除,vue中是这样操作的,删除后新的数据是吕和王,这时会进行比较,第一个节点的标签一样,值不一样,就会复用原来位置的标签,不会做删除和创建,直接将吕覆盖张,第一个节点就显示吕了,但是并没有删除,所以第一个节点还是被选中的。

示例中没有给key值,默认用了index做为key值。看下图为操作后的效果:

<template>
    <div>
        <ul>
            <liv-for="(item, index) in lists">
                <input type="checkbox" :value="item.text" />
                {{ item.text }}
            </li>
        </ul>
        <button @click="remove">删除</button>
    </div>
</template>
<script>
export default {
    data() { 
      return { 
        lists: [
          { id: 1, text: '张' }, 
          { id: 2, text: '吕' }, 
          { id: 3, text: '王' }
        ] 
      }; 
    },
    methods: { 
      remove() {
        //注意这里是shift
        this.lists.shift();    
      }  
    }
};
</script>


64a20492ec37d165973eaea47f4ec317.jpg

我们在选中最后一个节点的复选框(王的复选框),点击删除,这时候删除完会发现没有被选中的了。我们点击删除时,删除的是第一个数据,但dom中其实是删除的最后一个节点。因为在最后一个节点中的复选框是选中的,删除后,选中复选框没有被选中,说明被删除了。

fdf8107a3316de8c841933d965fe48cd.jpg

再分析:

当我们选择了最后一个多选框,删除第一个节点操作后,两个虚拟树进行比较,index为0和1由于还在,所以两个树之间的数据只是简单地移动。而index为2的节点(也就是最后一个节点)在新虚拟树上没有,于是直接删除。

使用数据中index做为key

<ul>
  <li v-for="(item, index) in lists" :key="index">
  <input type="checkbox" :value="item.text" />    
  {{ item.text }}
  </li>
</ul>


情况跟未加key的情况一样。分析与上面同。


使用数据中id做为key

<ul>
  <li v-for="(item, index) in lists" :key="item.id">
    <input type="checkbox" :value="item.text"/>  
    {{item.text}}
  </li>
</ul>

则不会出现上面的情况,这就减少了渲染错误。

3011207b045f79c9ff1573071043e615.jpg

92be7288f56f1b6d306fce64c0abe0f8.jpg

技术分享

苏南名片

  • 联系人:吴经理
  • 电话:152-1887-1916
  • 邮箱:message@jswusn.com
  • 地址:江苏省苏州市相城区

热门文章

Copyright © 2018-2025 jswusn.com 版权所有

技术支持:苏州网站建设  苏ICP备18036849号