zoukankan      html  css  js  c++  java
  • 10、v-for 为什么必须使用key(看链接)

    v-for 为什么必须使用key  

    https://www.cnblogs.com/lorin/articles/12395904.html

    vue 之前的版本没有限制 v-for 中配置 key 现在需要配置不然会报错

    为什么 必须使用key

    因为vue组件高度复用,增加Key可以标识组件的唯一性,key的作用主要是为了高效的更新虚拟DOM,后续再原理给大家讲解

    如何正确使用key


    VUE 使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;

    大多数都会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;

    栗子

    复制代码
    const list = [
        {
            id: 1,
            name: 'test1',
        },
        {
            id: 2,
            name: 'test2',
        },
        {
            id: 3,
            name: 'test3',
        },
    ]
    复制代码
    <div v-for="(item, index) in list" :key="index" >{{item.name}}</div>

    现在分两种插入方式给大家讲解

    1.在最后一条数据后再加一条数据

    复制代码
    const list = [
        {
            id: 1,
            name: 'test1',
        },
        {
            id: 2,
            name: 'test2',
        },
        {
            id: 3,
            name: 'test3',
        },
        {
            id: 4,
            name: '在最后添加的一条数据',
        },
    ]
    复制代码

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

    第二种情况 

    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
    复制代码

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

    是不是很惊奇,我明明只是插入了一条数据,怎么三条数据都要重新渲染?而我想要的只是新增的那一条数据新渲染出来就行了

    最好的办法是使用数组中不会变化的那一项作为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的那条数据,因此只要新渲染这一条数据就可以了,其他都是就复用之前的;

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

    vue和react的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设:

    1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
    2. 同一层级的一组节点,他们可以通过唯一的id进行区分。基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。

    引用React’s diff algorithm中的例子:

    diff1.jpg
    当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
    比如一下这个情况:
    diff2.jpg
    我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:
    diff3.jpg
    即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

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

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

  • 相关阅读:
    android 自定义Dialog
    【Head First Java 读书笔记】(四)对象的行为
    【Head First Java 读书笔记】(三)primitive主数据类型和引用
    【Android学习】自定义checkbox
    【Java】java中的compareTo和compare的区别
    【Java】对Map按key和value分别排序
    【Andoid学习】GridView学习
    【实习项目记录】(三)调整网络图片固定宽高
    【实习项目记录】(二) JSON
    【实习项目记录】(一)加密算法MD5和RSA
  • 原文地址:https://www.cnblogs.com/dream111/p/13498781.html
Copyright © 2011-2022 走看看