zoukankan      html  css  js  c++  java
  • react列表渲染时为什么尽量不要把索引设置为key值

    具体可见: https://juejin.im/post/6844904133430870024

    在react中,如果要渲染一个列表,我们会用map()函数将数组循环处理然后渲染到DOM,在处理循环时,“key” 是一个你需要包含的特殊字符串属性。

    很多时候,我们会使用当前列表的索引为key,但这样做真的好吗?

    要讨论这个问题,我们要从react的原理说起,我们react的执行步骤一般是:用state和jsx模板生成虚拟DOM,然后用虚拟DOM生成真实的 DOM,当我们state发生变化时,render函数执行,生成新的 虚拟DOM,然后比较新旧虚拟DOM的区别,找到区别,然后直接操作DOM,改变有区别的内容,这样比传统的操作DOM,极大的提升了性能。

    再说虚拟DOM,虚拟DOM其实就是一个JS对象(['div',{class:'app'},'item']),虚拟DOM核心之一是diff算法,diff算法的核心之一是同层对比,如图:


     
    同层对比

    如果在第一层div时就有出现区别,那么对比结束,直接更新真实DOM中对应的当前节点,以此类推。。。

    再说说key,假设我们在state中有一个列表[a,b,c],在遍历渲染时用索引作为key,那么就是这样:

    a 0
    b 1
    c 2
    

    如果我们执行一个操作,点击删除数组中的a, 我们的列表就是[b,c],在遍历渲染时仍然会用索引作为key,结果如下:

    b 0
    c 1
    
     
    区别

    如图 ,我们如果不用索引为key , 程序能快速的对比出差异,反之也能对出差异,但是必须对比整个虚拟DOM,
    这样,程序仍然能正常执行,只不过大大消耗了新旧虚拟DOM的对比的性能,并可能导致组件状态问题。

    再举一个vue的例子:为什么不能用index作为key?

    举个栗子:

    <template>
        <div v-for="(item, index) in list" :key="index" >{{item.name}}</div>
    </template>
    复制代码
    const list = [
        {
            id: 1,
            name: "Person1"
        },
        {
            id: 2,
            name: "Person2"
        },
        {
            id: 3,
            name: "Person3"
        },
        {
            id:4,
            name:"Person4"
        }
    ];
    复制代码

    此时,删除 “Person4” 是正常的,但是如果我删除 “Person2” 就会出现问题。

    删除前

    删除后

    这个时候,除了 Person1 之外,剩下的 Person3、Person4,因为被发现与相应 key 的绑定关系有变化,所以被重新渲染,这会影响性能。
    如果此时 list 的 item 是 select 的选项,其中 Person3 是选中的,这个时候 Person2 被删除了,用 index 作为 key 就会变成是 Person4 选中的了,这就产生了bug。

    如果使用唯一id作为key,删除 Person2 后,剩下的元素因为与 key 的关系没有发生变化,都不会被重新渲染,从而达到提升性能的目的。此时,list 的 item 作为 select 的选项,也不会出现上面所描述的bug。

  • 相关阅读:
    爱情的诗·1~5节
    人生的诗·381~385节
    人生的诗·375~380节
    python数据类型初始1
    python编码知识初始_ASCII码,Unicode,Utf-8,GBK
    Python运算符,逻辑运算
    python格式化输出%,while else
    pycharm使用教程链接+部分练习题01
    python流程控制-条件语句If,while循环
    python基础数据类型初始,用户交互
  • 原文地址:https://www.cnblogs.com/plBlog/p/13993817.html
Copyright © 2011-2022 走看看