最近在看一本名叫《深入浅出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 ,并没有预期让组件直接访问。

react为什么不用数组的下标来绑定key的更多相关文章

  1. C语言定义数组时使用枚举作为数组的下标 ——c99功能

    部分参考了https://blog.csdn.net/wq3028/article/details/76204690 同时在电脑上进行验证 //温度,电磁阀传感器序号,方便数组定位 typedef e ...

  2. js数组的用法以及数组根据下标(数值或字符)移除元素

    1.创建数组var array = new Array();var array = new Array(size);//指定数组的长度var array = new Array(item1,item2 ...

  3. angular,vue,react的基本语法—动态属性、事件绑定、ref,angular组件创建方式

    基本语法: 动态属性: vue: v-bind:attr="msg" :attr="msg" react: attr={msg} angular [attr]= ...

  4. react state为数组时插入值

    react state为数组时,如何插入值.在react里,一切皆是状态state,如果想通过改变state修改渲染效果,只能yongsetState.但是setState又是key:value格式, ...

  5. js数组的基本用法及数组根据下标(数值或字符)移除元素

    1.创建数组 var array = new Array(); var array = new Array(size);//指定数组的长度 var array = new Array(item1,it ...

  6. PHP 获取数组随意下标key的上一个prev和下一个next下标值

    PHP 获取数组随意下标key的上一个prev和下一个next下标值 <? php $xoops[1] = '小'; $xoops[2] = '孩'; $xoops[3] = '子'; $xoo ...

  7. Vue中 v-for 绑定key和不绑定key的区别

    首先,它们区别主要在于 虚拟DOM的复用,绑定key可以更好的复用,下面来详细讲一下 假如我们有一个数组 arr = [1,2,3,4],我们要在2后面插入一个值9: 如果绑定了key值,那么会是这样 ...

  8. Winform开发之ComboBox和ComboBoxEdit控件绑定key/value数据

    使用 ComboBox 控件绑定key/value值: 因为 ComboBox 是有 DataSource 属性的,所以它可以直接绑定数据源,如 DataTable.ListItem 等. 使用 Da ...

  9. Vue中v-for不绑定key会怎样

    Vue的v-for不绑定key,默认行为和绑定key="index"是差不多的,官方没有默认这种行为的情况下,会导致所有列表DOM重新渲染.key="index" ...

  10. forEach 循环数组 # for in 循环对象 key # for of 循环对象 value

    forEach 循环数组 # for in 循环对象 key # for of 循环对象 value

随机推荐

  1. ctfshow_web_1(困难题)

    CTFshow web1(困难题) 根据前面做题经验,看见登录框基本都是跑一下爆破,弱口令等等 这里用 dirmap 目录爆破爆出来有一个 www.zip 把他下载下来 看了 login.php 和 ...

  2. TeamViewer 9 和 10 即将停用 尝试切换到 Splashtop

    TeamViewer 9 和 TeamViewer 10 将于2021 年 6 月 1 日到期停用.当这两个版本的 TeamViewer 到期时,用户将无法再远程访问其计算机和设备. 这意味着要继续使 ...

  3. 记录一次对MQTT协议的渗透测试经历

    前言 由于工作需要,特意翻查了MQTT的相关漏洞,并一一学习复现,在此做以学习记录,没有恶意,如有抄袭,请私信作者删除. 技术文章仅供参考,此文所提供的信息只为网络安全人员对自己所负责的网站.服务器等 ...

  4. kubernets之横向伸缩pod与集群节点

    一  pod的自动伸缩容的应用背景 在面对负载并发过高的时候,我们或许希望能够提高RS,RC以及Deployment等的replicas的参数来增加pod的cpu,mem等,或者是通过提高每个容器的r ...

  5. Django与前端框架协作开发实战:高效构建现代Web应用

    title: Django与前端框架协作开发实战:高效构建现代Web应用 date: 2024/5/22 20:07:47 updated: 2024/5/22 20:07:47 categories ...

  6. 如何解决 IntelliJ Idea 编译 Java 项目时,找不到包或找不到符号的问题?

    执行 Maven Reimport 描述: 重新导入 Maven 包. 操作步骤: -> 选择 Project 目录右键 -> Maven -> Reimport 执行 Invali ...

  7. nginx重载流程nginx请求处理流程nginx单进程和多进程

    nginx重载流程 首先nginx会向master进程发送HUP信号[reload命令] master进程校验配置语法是否正确 master进程打开新的监听端口 master进程用心配置启动新的wor ...

  8. docker基础使用和资源限制

    为什么使用容器 docker设计目标: 提供简单的应用打包工具 开发人员和运维人员职责逻辑分离 多环境保持一致性 轻量级 kubernetes设计目标: 集中管理所有容器 资源编排 资源调度 弹性伸缩 ...

  9. itest(爱测试) 接口测试,敏捷测试管理平台 10.4.0 发布

    一:itest work 简介 itest work 开源敏捷测试管理,包含极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock,还有压测 ,又有丰富的统计分析,8合1工作站.可按 ...

  10. 利用ADB获取APP资源

    最近小编经常受到失眠的困扰,因为在编写一个安卓体能评定的软件,同时又在构思一个桌面管理应用,不管是构想还是操作上都遇到了很多难题,所以寄希望于小编手机上的一款软件,因为版权问题,就不说出它叫啥名字了. ...