vue中v-for的key的作用原理

vue中v-for的key的作用原理

一、原理

1.index作为key

1.1.首先我们要知道遍历数组的时候,如果不加key也不会报错,那为什么我们要加key呢?那就涉及到性能问题了。

1.2.我们都知道vue渲染数据的时候,并不是直接渲染成真实的DOM的,而是先渲染成虚拟的DOM,然后再渲染成真实的DOM的。那么在虚拟的DOM中就用到了key,因为虚拟DOM转换为真实的DOM的过程需要一个对比的过程,该对比过程需要diff算法,而diff算法需要用到key作为虚拟DOM中对象的标识。当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,然后vue对新的虚拟DOM和旧的虚拟DOM的差异进行比较,比较规则如下:

    1.2.1.旧虚拟DOM中找到了与新虚拟DOM相同的key
	1.2.2.若虚拟DOM中内容没变, 直接使用之前的真实DOM
	1.2.3.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
	1.2.4.旧虚拟DOM中未找到与新虚拟DOM相同的key
	1.2.5.创建新的真实DOM,随后渲染到到页面

1.3.用index作为key可能会引发的问题
若对数据进行逆序添加、逆序删除等破坏顺序操作,可以正常进行,但效率低。
从下面的第一张图对比新旧的两个虚拟的DOM,我们发现旧的虚拟DOM中第一条列表li的key是索引值0,文本内容是张三,而新的虚拟DOM的第一个列表key是0,而文本内容是老刘,虽然两者的key相同,但是文本内容不同,则vue会创建新的真实DOM,将新的内容替换旧的内容。
在这里我们会发现index索引值作为key的性能问题就显示出来了,你往数据的头部添加数据的时候,你会发现所有的数据渲染到页面时都要重新生成,而没有复用。
在新的虚拟DOM中,key为0的列表和旧的虚拟DOM中的key为0的列表对比,发现内容不同,就重新创建新的真实DOM,以此类推,新的虚拟DOM中key为1的列表是张三,而旧的虚拟DOM中本来是有张三的,但是之前被替换了,导致后面的数据都对应不上,所以所有DOM结点都要重新创建,这就出现了之前说的性能问题,这就是为什么要根据具体场景使用index作为key。
在这里插入图片描述

2.id作为key

**2.1.**如果使用id或者能够作为唯一标识的字段作为key这就不会出现用index作为key的问题。
通过下面的图可以看出,新的虚拟DOM的第一个列表key为id=“004”,然后去旧的虚拟DOM中查找key为id="004"的列表,发现没有这个key为id=“4”这个列表,则就创建新的真实DOM。而其他的列表发现key、内容、元素结点input相同,则新的虚拟DOM就会复用旧的虚拟DOM的列表生成真实的DOM,这样虚拟DOM的好处就体现出来了,大大的减少了性能问题。
在这里插入图片描述

二、代码解释

<title>key的原理</title>
<script type="text/javascript" src="../js/vue.js"></script>

<div id="root">
  <h2>人员列表(遍历数组)</h2>
  <button @click.once="add">添加一个老刘</button>
  <ul>
    <li v-for="(p,index) of persons" :key="index">
      {{p.name}}-{{p.age}}
      <input type="text">
    </li>
  </ul>
</div>

<script type="text/javascript">
  Vue.config.productionTip = false
  new Vue({
    el: '#root',
    data: {
      persons: [
        { id: '001', name: '张三', age: 18 },
        { id: '002', name: '李四', age: 19 },
        { id: '003', name: '王五', age: 20 }
      ]
    },
    methods: {
      add() {
       const p = { id: '004', name: '老刘', age: 40 }
        this.persons.unshift(p)
      }
    },
  })
</script>

在这里插入图片描述
在这里插入图片描述

上面的代码通过添加了一个列表数据,里面同时有一个输入框,你往输入框里输入内容的时候,利用index作为key就会有问题,你会发现数据错乱了。因为老刘的索引和张三的索引都为0,但是内容不同,那老刘和张三肯定不同嘛,但是里面的input是相同的,根据diff算法,相同那就复用呗,所以老刘就复用了张三的input,所以就会出现上图的问题。但是利用id或能够作为唯一标识的字段作为id就正常。

我是正在学习前端的菜鸟,如有错误,请及时指出~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值