v-for中的key

使用v-for更新已渲染的元素列表时,列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改则重新渲染这一项,否则复用之前的元素。我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法,有时也可能出现问题,原因如下:

在数组中插入一条数据:

const list = [
    {
        id: 1,
        name: 'test1',
    },
    {
        id: 4,
        name: '我是插队的那条数据',
    }
    {
        id: 2,
        name: 'test2',
    },
    {
        id: 3,
        name: 'test3',
    },
]
<div v-for="(item, index) in list" :key="index" >{{item.name}}</div>

此时除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染,导致性能下降:

之前的数据                                之后的数据

key: 0  index: 0 name: test1     key: 0  index: 0 name: test1
key: 1  index: 1 name: test2     key: 1  index: 1 name: 我是插队的那条数据
key: 2  index: 2 name: test3     key: 2  index: 2 name: test2
                                 key: 3  index: 3 name: test3

下面的例子是出现问题的:

<div id="app">
    <div>
      <input type="text" v-model="name">
      <button @click="add">添加</button>
    </div>
    <ul>
      <li v-for="(item, index) in list" :key="index">   // v-for不添加key或者key赋值为索引都会有问题
        <input type="checkbox"> {{item.name}}
      </li>
    </ul>
<script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        name: '',
        newId: 3,
        list: [
          { id: 1, name: '李斯' },
          { id: 2, name: '吕不韦' },
          { id: 3, name: '嬴政' }
         ]
      },
      methods: {
        add() {
         //注意这里是unshift
          this.list.unshift({ id: ++this.newId, name: this.name })
          this.name = ''
        }
      }
    });
  </script>
  </div>

当选中吕不为时,添加楠楠后选中的确是李斯,并不是我们想要的结果,我们想要的是当添加楠楠后,选中的还是吕不为

加了具有唯一性的key的checkbox跟内容进行了一个关联,会达到我们想要的效果:

<li v-for="(item, i) in list" :key="item.id">
    <input type="checkbox"> {{item.name}}
</li>

vue和react的虚拟DOM的Diff算法大致相同,首先看一下diff算法的处理方法,对操作前后的dom树同一层的节点进行对比,一层一层往下对比,如下图:

比如下边这种情况,我们希望可以在B和C之间加一个F:

Diff算法默认执行起来是这样的:

即把C更新成F,D更新成C,E更新成D,最后再插入E,这样很没有效率。所以我们需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。

因为vue组件采用高度复用,增加Key可以标识组件的唯一性,这样是为了高效的更新虚拟DOM。同理在react中使用map渲染列表时,也是必须加key,且推荐做法也是使用id,也是这个原因。

原文: https://www.jianshu.com/p/4bd5e745ce95

https://segmentfault.com/a/1190000013810844?utm_source=tag-newest

猜你喜欢

转载自www.cnblogs.com/xjy20170907/p/11511723.html