说说React diff的原理是什么?

news2025/1/11 19:59:57

一、是什么

跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升

而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处

传统diff算法通过循环递归对节点进行依次对比,效率低下,算法复杂度达到 O(n^3),react将算法进行一个优化,复杂度姜维O(n),两者效率差距如下图:

二、原理

react中diff算法主要遵循三个层级的策略:

  • tree层级
  • conponent 层级
  • element 层级

tree层级

DOM节点跨层级的操作不做优化,只会对相同层级的节点进行比较

只有删除、创建操作,没有移动操作,如下图:

react发现新树中,R节点下没有了A,那么直接删除A,在D节点下创建A以及下属节点

上述操作中,只有删除和创建操作

conponent层级

如果是同一个类的组件,则会继续往下diff运算,如果不是一个类的组件,那么直接删除这个组件下的所有子节点,创建新的

当component D换成了component G 后,即使两者的结构非常类似,也会将D删除再重新创建G

element层级

对于比较同一层级的节点们,每个节点在对应的层级用唯一的key作为标识

提供了 3 种节点操作,分别为 INSERT_MARKUP(插入)、MOVE_EXISTING (移动)和 REMOVE_NODE (删除)

如下场景:

通过key可以准确地发现新旧集合中的节点都是相同的节点,因此无需进行节点删除和创建,只需要将旧集合中节点的位置进行移动,更新为新集合中节点的位置

流程如下表:

  • index: 新集合的遍历下标。
  • oldIndex:当前节点在老集合中的下标
  • maxIndex:在新集合访问过的节点中,其在老集合的最大下标

如果当前节点在新集合中的位置比老集合中的位置靠前的话,是不会影响后续节点操作的,这里这时候被动字节不用动

操作过程中只比较oldIndex和maxIndex,规则如下:

  • 当oldIndex>maxIndex时,将oldIndex的值赋值给maxIndex
  • 当oldIndex=maxIndex时,不操作
  • 当oldIndex<maxIndex时,将当前节点移动到index的位置

diff过程如下:

  • 节点B:此时 maxIndex=0,oldIndex=1;满足 maxIndex< oldIndex,因此B节点不动,此时maxIndex= Math.max(oldIndex, maxIndex),就是1
  • 节点A:此时maxIndex=1,oldIndex=0;不满足maxIndex< oldIndex,因此A节点进行移动操作,此时maxIndex= Math.max(oldIndex, maxIndex),还是1
  • 节点D:此时maxIndex=1, oldIndex=3;满足maxIndex< oldIndex,因此D节点不动,此时maxIndex= Math.max(oldIndex, maxIndex),就是3
  • 节点C:此时maxIndex=3,oldIndex=2;不满足maxIndex< oldIndex,因此C节点进行移动操作,当前已经比较完了

当ABCD节点比较完成后,diff过程还没完,还会整体遍历老集合中节点,看有没有没用到的节点,有的话,就删除

三、注意事项

对于简单列表渲染而言,不使用key比使用key的性能,例如:

将一个[1,2,3,4,5],渲染成如下的样子:

<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>

后续更改成[1,3,2,5,4],使用key与不使用key作用如下:

1.加key
<div key='1'>1</div>             <div key='1'>1</div>    
<div key='2'>2</div>             <div key='3'>3</div> 
<div key='3'>3</div>  ========>  <div key='2'>2</div> 
<div key='4'>4</div>             <div key='5'>5</div> 
<div key='5'>5</div>             <div key='4'>4</div> 
操作:节点2移动至下标为2的位置,节点4移动至下标为4的位置。

2.不加key
<div>1</div>             <div>1</div>    
<div>2</div>             <div>3</div> 
<div>3</div>  ========>  <div>2</div> 
<div>4</div>             <div>5</div> 
<div>5</div>             <div>4</div> 
操作:修改第1个到第5个节点的innerText

如果我们对这个集合进行增删的操作改成[1,3,2,5,6]

1.加key
<div key='1'>1</div>             <div key='1'>1</div>    
<div key='2'>2</div>             <div key='3'>3</div> 
<div key='3'>3</div>  ========>  <div key='2'>2</div> 
<div key='4'>4</div>             <div key='5'>5</div> 
<div key='5'>5</div>             <div key='6'>6</div> 
操作:节点2移动至下标为2的位置,新增节点6至下标为4的位置,删除节点4。

2.不加key
<div>1</div>             <div>1</div>    
<div>2</div>             <div>3</div> 
<div>3</div>  ========>  <div>2</div> 
<div>4</div>             <div>5</div> 
<div>5</div>             <div>6</div>
操作:修改第1个到第5个节点的innerText

由于dom节点的移动操作开销是比较昂贵的,没有key的情况下要比有key的性能更好

参考文献

  • https://zhuanlan.zhihu.com/p/140489744
  • https://zhuanlan.zhihu.com/p/20346379

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1190853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Semantic-Guided Zero-Shot Learning for Low-Light ImageVideo Enhancement

论文阅读之无监督低光照图像增强 Semantic-Guided Zero-Shot Learning for Low-Light Image/Video Enhancement 代码&#xff1a; https://github.com/ShenZheng2000/SemantiGuided-Low-Light-Image-Enhancement 在低光条件下增加亮度的一个可行方法是使用更高的ISO或更长时间…

AI:76-基于机器学习的智能城市交通管理

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…

leetcode:LCP 11. 期望个数统计(python3解法)

难度&#xff1a;简单 某互联网公司一年一度的春招开始了&#xff0c;一共有 n 名面试者入选。每名面试者都会提交一份简历&#xff0c;公司会根据提供的简历资料产生一个预估的能力值&#xff0c;数值越大代表越有可能通过面试。 小 A 和小 B 负责审核面试者&#xff0c;他们均…

计算机二级公共基础

知识点 1.树 树的最大层次&#xff08;最长路径的长度&#xff09;称为树的深度 二叉树的后件最多不超过两个 满二叉树&#xff1a;除最后一层每一层的所有节点都有两个子节点。&#xff08;满二叉树一定是完全二叉树&#xff09; 完全二叉树&#xff1a;所有节点均达到最大数…

显著提升!| (WOA)融合模拟退火和自适应变异的混沌鲸鱼优化算法应用于函数寻优

鲸鱼优化算法(whale optimization algorithm,WOA)是由Mirjalili和Lewis[1]于2016年提出的一种新型群体智能优化搜索方法,它源于对自然界中座头鲸群体狩猎行为的模拟&#xff0c;与其它群体智能优化算法相比&#xff0c;WOA算法结构新颖, 控制参数少&#xff0c;在许多数值优化和…

JavaScript使用Ajax

Ajax(Asynchronous JavaScript and XML)是使用JavaScript脚本&#xff0c;借助XMLHttpRequest插件&#xff0c;在客户端与服务器端之间实现异步通信的一种方法。2005年2月&#xff0c;Ajax第一次正式出现&#xff0c;从此以后Ajax成为JavaScript发起HTTP异步请求的代名词。2006…

【论文阅读】DALL·E: Zero-Shot Text-to-Image Generation

OpenAI第一代文本生成图片模型 paper&#xff1a;https://arxiv.org/abs/2102.12092 DALLE有120亿参数&#xff0c;基于自回归transformer&#xff0c;在2.5亿 图片-文本对上训练的。实现了高质量可控的text to image&#xff0c;同时也有zero-shot的能力。 DALL-E没有使用扩…

汽车螺丝扭力标准/汽车常见螺栓扭矩参照

汽车螺丝扭力标准参照表如下&#xff1a; 1、支座与车身螺栓(13MM)--25Nm&#xff1b; 2、支座与车身螺栓(18MM)--40Nm90度/50Nm&#xff1b; 3、支座与发动机支座螺栓(18Mm)--100Nm&#xff1b; 4、支座与车身螺栓(13MM)--25Nm&#xff1b; 5、支座与车身螺栓(18MM)--40N…

【Rust日报】2023-11-08 RustyVault -- 基于 rust 的现代秘密管理系统

RustyVault -- 基于 rust 的现代秘密管理系统 RustyVault 是一个用 Rust 编写的现代秘密管理系统。RustyVault 提供多种功能&#xff0c;支持多种场景&#xff0c;包括安全存储、云身份管理、秘密管理、Kubernetes 集成、PKI 基础设施、密码计算、传统密钥管理等。RustyVault 可…

面试10000次依然会问的【线程池】,你还不会?

线程池的基本概念 线程池是一种基于池化技术的线程使用方式&#xff0c;它允许我们有效地管理和复用线程&#xff0c;减少线程的创建和销毁的开销&#xff0c;从而提高系统的响应速度。在Java中&#xff0c;线程池的管理主要通过ThreadPoolExecutor类来实现。 线程池的定义与…

docker可视化

什么是portainer&#xff1f; portainer就是docker图形化界面的管理工具&#xff0c;提供一个后台面板供我们操作 目前先用portainer(先用这个)&#xff0c;以后还会用到Rancher(CI/CD在用) 1.下载portainer 9000是内网端口&#xff0c;8088是外网访问端口 docker run…

19 数据中心详解

1、数据中心的概念 其实平时我们不管是看新闻&#xff0c;视频&#xff0c;下载文件等&#xff0c;最终访问的目的地都是在数据中心里面。数据中心存放的是服务器&#xff0c;区别于我们平时使用的笔记本或者台式机。 机架&#xff1a;数据中心的服务器被放在一个个叫作机架&…

Go 接口:Go中最强大的魔法,接口应用模式或惯例介绍

Go 接口&#xff1a;Go中最强大的魔法,接口应用模式或惯例介绍 文章目录 Go 接口&#xff1a;Go中最强大的魔法,接口应用模式或惯例介绍一、前置原则二、一切皆组合2.1 一切皆组合2.2 垂直组合2.2.1 第一种&#xff1a;通过嵌入接口构建接口2.2.2 第二种&#xff1a;通过嵌入接…

Guli商城-商品服务-API-三级分类-配置网关路由与路径重写

启动人人fast服务&#xff1a; 打开本地的前端项目&#xff0c;启动&#xff1a; 命令&#xff1a;npm run dev 账号密码&#xff1a;admin/admin 对应的数据库&#xff1a; 接下来在商品系统目录中添加子菜单&#xff1a; 数据库中可以看到记录 退出账号&#xff0c;重新登录…

vue中实现千位分隔符

vue中实现千位分隔符有两种&#xff0c;一种是某一个字段转换&#xff0c;一种是表格table中的整列字段转换 比如将3236634.12&#xff0c;经过转换后变为 3,236,634.12 1. 某一个字段转换 写js方法&#xff1a; export function numberExchange(value){if (!value) return…

Android自定义 View惯性滚动效果(不使用Scroller)

效果图&#xff1a; 前言&#xff1a; 看了网上很多惯性滚动方案&#xff0c;都是通过Scroller 配合 computeScroll实现的&#xff0c;但在实际开发中可能有一些场景不合适&#xff0c;比如协调布局&#xff0c;内部子View有特别复杂的联动效果&#xff0c;需要通过偏移来配合…

JavaScript从入门到精通系列第三十二篇:详解正则表达式语法(一)

文章目录 一&#xff1a;正则表达式 1&#xff1a;量词设置次数 2&#xff1a;检查字符串以什么开头 3&#xff1a;检查字符串以什么结尾 4&#xff1a; 同时使用开头结尾 5&#xff1a;同值开头同值结尾 二&#xff1a;练习 1&#xff1a;检查是否是一个手机号 大神链…

(附源码)基于Springboot智慧园区管理系统-计算机毕设 88160

Springboot智慧园区管理系统的开发 摘要 随着互联网趋势的到来&#xff0c;互联网概念越来越盛行&#xff0c;园区管理最好方式就是建立自己的互联网系统。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Springboot框架建设智慧园区管理系统。 本设计主…

线性代数(五) | 矩阵对角化 特征值 特征向量

文章目录 1 矩阵的特征值和特征向量究竟是什么&#xff1f;2 求特征值和特征向量3 特征值和特征向量的应用4 矩阵的对角化 1 矩阵的特征值和特征向量究竟是什么&#xff1f; 矩阵实际上是一种变换,是一种旋转伸缩变换&#xff08;方阵&#xff09; 不是方阵的话还有可能是一种…

博阳精讯、凡得科技访问上海斯歌:共探BPM流程服务新高地

10月27日下午&#xff0c;来自博阳精讯、凡得科技的流程领域专家、领导一行参观访问了上海斯歌总部。三方举行了深度交流会谈&#xff0c;分享了彼此对流程领域的前沿洞察和技术实践&#xff0c;共同探索了BPM流程服务科技力与价值力的新高地。 本次研讨会上&#xff0c;博阳精…