React中的Diffing算法

news/2024/7/15 19:16:31 标签: javascript, 前端, react.js

提到这个算法,就必须说一下关于Key的事情了。
其实每个组件中的每个标签都会有一个key,只不过有的必须显示的指定,有的可以隐藏。
如果生成的render出来后就不会改变里面的内容,那么你不需要指定key(不指定key时,React也会生成一个默认的标识),或者将index作为key,只要key不重复即可。
但是如果你的标签是动态的,是有可能刷新的,就必须显示的指定key。必须上面案使用map进行便利的时候就必须指定Key:

javascript">this.state.num.map((n,index)=>{
  return <div className="news" key={index} >新闻{n}</div>
 })

这个地方虽然显示的指定了key,但是官网并不推荐使用Index作为Key去使用
这样会很有可能会有效率上的问题
举个例子:
在一个组件中,我们先创建了两个对象,通过循环的方式放入< li>标签中,此时key使用的是index。

javascript">person:[
  {id:1,name:"张三",age:18},
  {id:2,name:"李四",age:19}
]

this.state.person.map((preson,index)=>{
  return  <li key = {index}>{preson.name}</li>
})

如下图展现在页面中:
此时,我们想在点击按钮之后动态的添加一个对象,并且放入到li标签中,在重新渲染到页面中。
我们通过修改State来控制对象的添加。

javascript"><button onClick={this.addObject}>点击增加对象</button>
addObject = () =>{
  let {person} = this.state;
  const p = {id:(person.length+1),name:"王五",age:20};
  this.setState({person:[p,...person]});
}

如下动图所示:
这样看,虽然完成了功能。但是其实存在效率上的问题, 我们先来看一下两个前后组件状态的变化:
我们发现,组件第一个变成了王五,张三和李四都移下去了。因为我们使用Index作为Key,这三个标签的key也就发生了改变【张三原本的key是0,现在变成了1,李四的key原本是1,现在变成了2,王五变成了0】在组件更新状态重新渲染的时候,就出现了问题:
因为react是通过key来比较组件标签是否一致的,拿这个案例来说:
首先,状态更新导致组件标签更新,react根据Key,判断旧的虚拟DOM和新的虚拟DOM是否一致
key = 0 的时候 旧的虚拟DOM 内容是张三 新的虚拟DOM为王五 ,react认为内容改变,从而重新创建新的真实DOM.
key = 1 的时候 旧的虚拟DOM 内容是李四,新的虚拟DOM为张三,react认为内容改变,从而重新创建新的真实DOM
key = 2 的时候 旧的虚拟DOM没有,创建新的真实DOM
这样原本有两个虚拟DOM可以复用,但都没有进行复用,完完全全的都是新创建的;这就导致效率极大的降低。
其实这是因为我们将新创建的对象放在了首位,如果放在最后其实是没有问题的,但是因为官方并不推荐使用Index作为key值,我们推荐使用id作为key值。从而完全避免这样的情况。
用index作为key可能会引发的问题:
1。若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:
会产生错误DOM更新 界面有问题。
3,注意! 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
开发如何选择key?
最好使用每一条数据的唯一标识作为key 比如id,手机号,身份证号
如果确定只是简单的展示数据,用Index也是可以的
而这个判断key的比较规则就是Diff算法
Diff算法其实就是react生成的新虚拟DOM和以前的旧虚拟DOM的比较规则:

  • 如果旧的虚拟DOM中找到了与新虚拟DOM相同的key:
    • 如果内容没有变化,就直接只用之前旧的真实DOM
    • 如果内容发生了变化,就生成新的真实DOM
  • 如果旧的虚拟DOM中没有找到了与新虚拟DOM相同的key:
    • 根据数据创建新的真实的DOM,随后渲染到页面上

http://www.niftyadmin.cn/n/1008895.html

相关文章

leetcode 88.合并两个有序数组

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;合并两个有序数组 ⭕️ 代码&#xff1a; /*思路&#xff1a;双指针问题1.从前往后拷贝依次比较两个数组元素的较小值&#xff0c;较小值先拷贝- 问题&#xff1a;从前拷贝会造成覆盖(有问题)2.从后往前拷贝依次比较两个…

电子电气架构——车载DoIP通信

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人们会在生活中不断攻击你。他们的主要武器是向你灌输对自己的怀疑:你的价值、你的能力、你的潜力。他们往往会将此伪装成客观意见,但无一例外的是…

[python][pcl]python-pcl案例之圆柱模型分割(Cylinder model segmentation)

测试环境&#xff1a; pcl1.12.1 python-pcl0.3.1 python3.7 代码&#xff1a; # -*- coding: utf-8 -*- # Cylinder model segmentation # http://pointclouds.org/documentation/tutorials/cylinder_segmentation.php#cylinder-segmentation # dataset : https://raw.gi…

MicroBlaze系列教程(10):AXI_HWICAP的使用

文章目录 @[toc]1. AXI HWICAP简介2. MicroBlaze硬件配置3. 常用函数4. 使用示例1:读取IDCODE5. 使用示例2:从指定地址重新配置6. 参考资料本文是Xilinx MicroBlaze系列教程的第10篇文章。 1. AXI HWICAP简介 AXI_HWICAP,是把ICAP原语封装成了一个AXI接口的IP核,可以通过M…

source insight小键盘在vim中不能使用数字(数字按键变英文)

文章目录 问题描述解决办法注意&#xff1a; 问题描述 在使用source insight登录远程服务器并使用vim编辑模式时&#xff0c;出现数字键盘的0-9变成了yxwvutsrqp情况。 解决办法 注意&#xff1a; 如果你点了save as…的话&#xff0c;会让你保存untitled.key文件到你指定的路…

xenomai内核解析--xenomai实时线程创建流程

版权声明&#xff1a;本文为本文为博主原创文章&#xff0c;未经同意&#xff0c;禁止转载。如有错误&#xff0c;欢迎指正&#xff0c;博客地址&#xff1a;https://blog.csdn.net/qq_22654551?typeblog 文章目录 问题概述1 libCobalt中调用非实时POSIX接口2 阶段1 linux线程…

【实证分析】地区竞争、推广数字普惠金融与绿色经济效率

研究内容 基于考虑非期望产出的 Super-SBM 模型测算了 2011—2018 年中国 265 个地级市的绿色经济效率,综合运用面板模型、空间杜宾模型,系统分析了地区竞争下推广数字普惠金融对绿色经济效率的影响效应。研究发现:(1)绿色经济效率存在显著正向空间溢出效应,地理距离与经济差异…

Linux--阅读文本指令:more、less

生成10000行数字并将其写入普通文件的指令&#xff1a; count0; while [ $count -le 10000 ]; do echo "hello bit ${count}"; let count; done > file.txt 直接cat < file.txt会刷屏的&#xff0c;故引入more 注&#xff1a;enter键控制下翻&#xff0c;q直…