*vue v-for中 key 值的作用—key不能用index的值*

1. v-for中的key

用 v-for 更新已渲染过的元素列表时,它默认使用“就地复用”的策略。如果数据项的顺序发生了改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处的每个元素。因此通过为每个列表项提供一个 key 值,来以便 Vue 跟踪元素的身份,从而高效的实现复用。这个时候 key 的作用是为了高效的更新渲染虚拟 DOM。

当vue.js使用v-for更新已渲染的元素列表时,默认用 “就地复用” 策略;如果数据项被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是简单复用此处的每个元素,并且确保他在特定索引下显示已被渲染的每个元素。所以一句话,key的作用主要是为了高效的更新虚拟DOM。列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;

  • 1.1. 我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;
{{item.name}}
const list = [ { id: 1, name: 'test1', }, { id: 2, name: 'test2', }, { id: 3, name: 'test3', }, ]

上面这种是我们做项目中常用到的一种场景,因为不加key,vue现在直接报错,所以我使用index作为key;下面列举两种常见的数据更新情况

  • 1.1.1. 在最后一条数据后再加一条数据
const list = [
    {
        id: 1,
        name: 'test1',
    },
    {
        id: 2,
        name: 'test2',
    },
    {
        id: 3,
        name: 'test3',
    },
    {
        id: 4,
        name: '我是在最后添加的一条数据',
    },
]

此时前三条数据直接复用之前的,新渲染最后一条数据,此时用index作为key,没有任何问题;

  • 1.1.2. 在中间插入一条数据
const list = [
    {
        id: 1,
        name: 'test1',
    },
    {
        id: 4,
        name: '我是插队的那条数据',
    }
    {
        id: 2,
        name: 'test2',
    },
    {
        id: 3,
        name: 'test3',
    },
]

此时更新渲染数据,通过index定义的key去进行前后数据的对比,发现

之前的数据                         之后的数据

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

通过上面清晰的对比,发现除了第一个数据可以复用之前的之外,另外三条数据都需要重新渲染;

  • ?思考:
    是不是很惊奇,我明明只是插入了一条数据,怎么三条数据都要重新渲染?而我想要的只是新增的那一条数据新渲染出来就行了
  • 1.2. 最好的办法是使用数组中不会变化的那一项作为key值,对应到项目中,即每条数据都有一个唯一的id,来标识这条数据的唯一性;使用id作为key值,我们再来对比一下向中间插入一条数据,此时会怎么去渲染
之前的数据                               之后的数据

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

现在对比发现只有一条数据变化了,就是id为4的那条,因此只要新渲染着一条数据就可以了,其他都是复用之前的

2. v-if 中使用 key

由于 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此当我们使用 v-if 来实现元素切换的时候,如果切换前后含有相同类型的元素,那么这个元素就会被复用。如果是相同的 input 元素,那么切换前后用户的输入不会被清除掉,这样是不符合需求的。因此我们可以通过使用 key 来唯一的标识一个元素,这个情况下,使用 key 的元素不会被复用。这个时候 key 的作用是用来标识一个独立的元素。

3. 总结:

  • 真正的原因和vue无关,而是Virtual DOM 使用Diff算法实现的原因

从虚拟DOM的Diff算法实现的角度去解释一下

  • 3.1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
  • 3.2. 同一层级的一组节点,他们可以通过唯一的id进行区分。
    基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从0降到了0
    引用React’s diff algorithm中的例子:
    key.jpeg
  • 当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。比如一下这种情况:


    key1.jpeg
  • 我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:


    key2.jpeg

    即把C更新成F,D更新成C,E更新成D,最后插入E,是不是很没有效率??

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

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

转载:https://segmentfault.com/a/1190000013810844

你可能感兴趣的:(*vue v-for中 key 值的作用—key不能用index的值*)