最近在看一本名叫《深入浅出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. salesforce零基础学习(一百三十六)零碎知识点小总结(八)

    本篇参考: Salesforce LWC学习(七) Navigation & Toast https://developer.salesforce.com/docs/platform/lwc/ ...

  2. 复杂模式的两个List与Map合并为一个Map的拼接;笛卡尔乘积处理数据问题

    简介 (Introduction): 背景 数据从多个表中获取,每个表的数据条数不是唯一的,最后结果要拼接成一个Map<String,Object>的模式封装所有数据,每个数据是一条. 结 ...

  3. 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(12.A)- uSDHC eMMC启动时间(RT1170)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 uSDHC eMMC启动时间. 本篇是 i.MXRT1170 启动时间评测第五弹,前四篇分别给大家评测了 ...

  4. 服务器电源管理(Power Management States)

    目录 文章目录 目录 EIST(智能降频技术) 硬件 固件 操作系统 EIST(智能降频技术) EIST 能够根据不同的 OS(操作系统)工作量自动调节 CPU 的电压和频率,以减少耗电量和发热量.它 ...

  5. pageoffice在线打开word文件加盖电子印章

    一.加盖印章的 js 方法 js方法 二.常见使用场景 1.常规盖章.弹出用户名.密码输入框,选择对应印章. 点击盖章按钮弹出用户名密码登录框,登录以后显示选择电子印章. document.getEl ...

  6. 我们小公司,哪像华为一样,用得上IPD(集成产品开发)?

    在一些咨询或活动现场,我们经常听到有朋友说:我们是小公司,IPD(集成产品开发)太厚重了,不适合我们.但--到底哪里不合适? 提及IPD,成功的案例多以大公司为主:20世纪90年代,IBM在激烈的市场 ...

  7. sqlerver 报错5120 无法为该请求检索数据 系统找不到指定路径

    背景: 数据库mdf文件所在盘符F盘被删除了,也就是文件不存在了,sqlserver管理器打开就报错5120,并且正常路径的数据库也不显示出来. 要让正常的数据库显示出来,就需要删除掉已经没有的数据库 ...

  8. 一文读懂Spring的SPI机制

    一. 从类加载说起 Java中的类加载器负载加载来自文件系统.网络或者其他来源的类文件.jvm的类加载器默认使用的是双亲委派模式.三种默认的类加载器Bootstrap ClassLoader.Exte ...

  9. 阿里巴巴 MySQL 数据库之 SQL 语句规约 (三)

    SQL 语句规约 强制部分 [强制] 不要使用 count(列名) 或 count(常量) 来替代 count(*),count(*) 是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NU ...

  10. TS码流解析(三)PES

    我们常说的音视频数据流在TS中被称为Elementary Stream(ES),也称为原始码流(裸流).ES流本身不含有传输所需的所有信息,为了在传输过程中同时携带PTS(Presentation T ...