React之diff原理

news2024/9/26 1:16:06

一、是什么

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

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

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

二、原理

reactdiff算法主要遵循三个层级的策略:

  • 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的性能更好

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

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

相关文章

为什么亚马逊卖家一定要有独立站?新手低成本快速搭建跨境电商独立站完整图文教程

效果展示 翻译助手 一、购买域名 二、购买主机托管 三、搭建独立网站 四、网站装修设计 五、网站迁移 六、补充 前言&#xff1a;为什么亚马逊卖家一定要有独立站&#xff1f; 先来谈谈为什么亚马逊卖家一定得有独立站&#xff0c;从我一些个人经历来看&#xff0c;有独…

C语言程序设计——题目:用*号输出字母C的图案。程序分析:可先用‘*‘号在纸上写出字母C,再分行输出。

题目&#xff1a;用*号输出字母C的图案。 程序分析&#xff1a;可先用*号在纸上写出字母C&#xff0c;再分行输出。 #include<stdio.h> int main() {printf(" *****\n");printf(" *\n");printf("*\n");printf("*\n");printf(&…

如何一键核实验证身份证的真伪?

据报道&#xff0c;今年10月10日&#xff0c;广东省佛山市朱某因生活琐事与丈夫发生争吵&#xff0c;民警发现她的身份证有问题。 在民警打算进一步了解情况&#xff0c;查看夫妻二人的身份证件时&#xff0c;朱某的身份证引起了民警的注意。这张身份证表面很光滑&#xff0c;…

【JAVA学习笔记】34 - 房屋出租系统(综合性强)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_chapter09/src/com/yinhai/houserent 一、项目需求说明 实现基于文本界面的房屋出租系统&#xff0c;能够实现对房屋信息的添加、修改和删除&#xff08;用数组实现&#xff09;&#xff0c;并能够…

大学兼职教师管理系统 用JAVA语言开发

一、项目介绍 基于VueSpringBootMySQL的大学兼职教师管理系统包含学生管理、教师管理、课程档案管理、课程评价管理、课程考勤管理、授课管理、课程成绩管理教龄/薪资分析可视化图表&#xff0c;还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管…

canal五部曲-canal是如何处理insert幂等性的

canal使用了Rocketmq来接收mysql采集的binlog的事件&#xff0c;做到采集和处理的解耦。同时满足一次采集多方消费的需求。那么既然使用到Rocketmq就一定会存在MQ消费超时或是处理失败MQ重发的问题。 那么canal是如何处理MQ重复消费幂等性问题的呢 一般&#xff0c;在业务上我…

网络安全保险行业面临的挑战与变革

保险业内大多数资产类别的数据可以追溯到几个世纪以前&#xff1b;然而&#xff0c;网络安全保险业仍处于初级阶段。由于勒索软件攻击、高度复杂的黑客和昂贵的数据泄漏事件不断增加&#xff0c;许多网络安全保险提供商开始感到害怕继续承保更多业务。 保险行业 根据最近的路…

电脑每过几天就要自动更新,一键教你解决

windows更新&#xff0c;暂停更新最多只能选5个周&#xff0c;还是很麻烦&#xff0c;那么看下图&#xff0c;教你如何改为10年后&#xff1b; 建立一个txt文件&#xff0c;复制下述内容&#xff0c;然后保存&#xff0c;再把后缀名改为.reg,运行一下就可以轻松改为10年了&…

Python爬虫网易云音乐,Tkinter制作音乐播放器

目录 一、效果展示 二、环境 三、实现过程 四、源码 一、效果展示 页面的美化以及功能还有待升级~ 先来说一下已有功能吧&#xff1a; 可以在搜索框中通过歌曲或歌手名称进行搜索&#xff0c;效果和在网易云官网搜索一样。 点击开始下载&#xff0c;就会将搜索结果的第一…

小程序实现圆环进度

一&#xff1a;需求 小程序中要展示进度&#xff0c;要求类似示例图&#xff0c;用圆环形式展示进度&#xff0c;那这该如何实现呢&#xff1f;这一篇文章主要讲的就是这样一个功能。 二&#xff1a;实现 实现的大致流程是把圆环进度条封装成一个组件&#xff0c;然后在需要使…

【开源框架】Glide的图片加载流程

引入依赖 以下的所有分析都是基于此版本的Glide分析 //引入第三方库glide implementation com.github.bumptech.glide:glide:4.11.0 annotationProcessor com.github.bumptech.glide:compiler:4.11.0分析 Glide的使用就是短短的一行代码 Glide.with(this).load("xxx&q…

Dell R720服务器已有win10系统下安装Ubuntu10.04双系统

先在win10下进磁盘管理&#xff0c;分配空间 重启电脑&#xff0c;开机时按F11进入BIOS。 one-shot boot&#xff0c;选U盘 datatraveler 我原来装的是ubuntu18&#xff0c;ubuntu18升级成了ubuntu20&#xff0c;但是apt-get upgrade有很多问题&#xff0c;所以只能重装。 …

数据结构与算法之矩阵: Leetcode 134. 螺旋矩阵 (Typescript版)

螺旋矩阵 https://leetcode.cn/problems/spiral-matrix/ 描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示…

第19章 Dubbo

本文中所有的原理及流程都是针对Dubbo3.0.2.1版本 19.1 谈谈你对Dubbo的理解 难度:★★★★ 重点:★★ 白话解析 1、背景:参考18.13题,这里不在赘述。 2、简介:Dubbo在3.x版本之前都只是一个高性能的RPC框架,但是在3.x版本之后,官网的描述变了,Dubbo已经升级成一个等…

ke8学校陈老师H5

目录 例一&#xff1a; 1label for与表单元素建立关联 2鼠标选中区域 3classlist属性&#xff1a;更换类选择器。添加、删除、切换和查询一个元素上的类。 4nextElementSibling属性 5title属性&#xff1a;鼠标放上去会有提示信息 6placeholder属性&#xff1a;填了就有…

Linux常用命令——cksum命令

在线Linux命令查询工具 cksum 检查文件的CRC是否正确 补充说明 cksum命令是检查文件的CRC是否正确&#xff0c;确保文件从一个系统传输到另一个系统的过程中不被损坏。这种方法要求校验和在源系统中被计算出来&#xff0c;在目的系统中又被计算一次&#xff0c;两个数字进行…

【RuoYi-Vue-Plus】学习笔记 50 - 集成 JSEncrypt 实现请求加密传输(源码)

文章目录 前言框架版本前端服务端 框架集成前端集成1、总览2、代码实现服务端集成1、总览2、代码实现2.1、配置信息 application.yml2.2、配置类 ApiDecryptProperties2.3、过滤器 CryptoFilter2.4、包装类 DecryptRequestBodyWrapper2.5、加解密工具类 EncryptUtils2.6、自动装…

Windows环境部署流媒体服务器ZLMediaKit

参考资料 快速开始 ZLMediaKit/ZLMediaKit Wiki GitHub 环境准备 序号名称版本作用下载地址1Microsoft Visual Studio链接&#xff1a;https://pan.baidu.com/s/1DoWjNZ72Y8YpGpSTY0CNKw 提取码&#xff1a;pv6a2opensslWin32/Win64 OpenSSL Installer for Windows - Shi…

聚观早报 | vivo Y100官宣;极氪001 FR将上市

【聚观365】10月25日消息 vivo Y100官宣 一极氪001 FR将上市 特斯拉加速扩张 苹果扩大招聘力度 小米澎湃OS实现历史性跨越 vivo Y100官宣 vivo Y系列是vivo存在比较久的入门系列&#xff0c;主打千元价位的线下市场&#xff0c;在消费者中有着不错的口碑。而不久前一款型…

R语言代码示例

以下是一个使用R语言和httrOAuth库的下载器程序&#xff0c;用于下载的内容。程序使用以下代码。 # 安装和加载必要的库 install.packages("httr") install.packages("httrOAuth") library(httr) library(httrOAuth) ​ # 设置 http_proxy <- "du…