zoukankan      html  css  js  c++  java
  • react为什么不用数组的下标来绑定key

    最近在看一本名叫《深入浅出React和Redux》这一书,里面谈到了react的dom更新比对,记录一下。

    假设有这么一个组件

    <ul>
        <ListItem text="first" />
        <ListItem text="second" />
        <ListItem text="third" />
    </ul>
    

    现在,我们在这个组件的前面插入一个新的组件<ListItem text='zero' />

    <ul>
        <ListItem text="zero" />
        <ListItem text="first" />
        <ListItem text="second" />
    </ul>
    

    思考,怎么更新dom是最优的,react是去怎么更新?

    按照我们的思维,最优的更新dom就是去把新增一个ListItem组件,放在第一个。把之前的第一个组件<ListItem text="first" /> 以及第二个组件<ListItem text="second" />往后挪一位。这样的结果是最好的。

    可是react不是这样更新的!

    它先去比较第一个ListItem组件,发现组件上的textfirst变成了zero,需要更新。第二个组件text之前的second变成了first,也需要更新,最后新创建一个组件,把它的text设置为second。react就完成了它的更新。

    当然, React 并不是没有意识到这个问题,所以 React 提供了方法来克服这种浪费,不过需要开发人员在写代码的时候提供一点小小的帮助,这就是 key 的作用。

    key的用法

    在 React 的眼里,确定每一个组件在组件序列中的唯一标识就是它的位置,所以
    它也完全不懂哪些子组件实际上并没有改变,为了让 React 更加“聪明”,就需要开发者
    提供一点帮助。

    如果在代码中明确地告诉 React 每个组件的唯一标识,就可以帮助 React 在处理这个
    问题时聪明很多,告诉 React 每个组件“身份证号”的途径就是 key 属性。

    • 把之前的代码加上key
    <ul>
        <ListItem key={1}  text="first" />
        <ListItem key={2} text="second" />
        <ListItem key={3} text="third" />
    </ul>
    

    现在再去插入一个ListItem组件放在最前面,让它key为0

    <ul>
        <ListItem key={0} text="zero" />
        <ListItem key={1} text="first" />
        <ListItem key={2} text="second" />
    </ul>
    

    现在,react根据key值,知道了第二个第三个组件是之前的第一个第二个,所以react会创建一个ListItem组件放在第一位,对于原有的两个组件只用原有的props触发更新。这里就需要组件内部的shouldComponentUpdate的钩子函数进行判断来减少不必要的更新。

    但是这个 key 值只是唯一还不足够,这个 key 值还需要是稳定不变的,试想,如果
    key 值虽然能够在每个时刻都唯一,但是变来变去,那么就会误导 React 做出错误判断,
    甚至导致错误的渲染结果。

    <ul>
        {
            Arr.map((item,index)=>(<ListItem key={index} text={item.text} />))
        }
    </ul>
    

    用数组下标作为 key ,看起来 key 值是唯一的,但是却不是稳定不变的,随着 Arr
    数组值的不同,同样一个Listltem 实例在不同的更新过程中在数组中的下标完全可能不
    同,把下标当做 key 就让 React 彻底乱套了。

    需要注意,虽然 key 是一个 prop ,但是接受 key 的组件并不能读取到 key 的值,因为key ref React 保留的两个特殊 prop ,并没有预期让组件直接访问。

  • 相关阅读:
    go语言教程零基础入门到精通
    php探针文件内容
    一篇文章揭穿创业公司的套路
    Google资深工程师深度讲解Go语言面向接口(五)
    完全解析<atlalloc.h>
    巧妙的Section — — 剖析ATL OBJECT_MAP的自动建立
    ATL中的各种CriticalSection
    C++中的INL
    如何剖析一个类
    ATL线程模型解析
  • 原文地址:https://www.cnblogs.com/kongyijilafumi/p/14304684.html
Copyright © 2011-2022 走看看