React之diff原理
一、是什么
跟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
的性能更好
相关文章:

React之diff原理
一、是什么 跟Vue一致,React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,使我们的页面的构建效率提到了极大的提升 而diff算法就是更高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处 传统diff算法通过循环递归对节点进行依…...

ElasticSearch中关于Nasted嵌套查询的介绍:生动案例,通俗易懂,彻底吸收
题注:随着对ES接触的越来越深入,发现此前了解的ES知识点有点单薄,特此寻来ES知识点汇总成的一个思维导图,全面了解自己掌握了哪些,未掌握哪些。此外,作者斌并没有足够的精力学习ES全部的知识点,…...
系列二、Spring的优缺点是什么
一、Spring的优缺点是什么 1.1、优点 集中管理对象,降低对象和对象之间的耦合性,方便维护对象;在不修改代码的情况下可以对业务代码进行增强,减少重复代码,提高开发效率,方便维护;提高开发效率…...
ESP32网络开发实例-HTTP-GET请求
HTTP-GET请求 文章目录 HTTP-GET请求1、HTTP GET请求2、软件准备3、硬件准备4、代码实现4.1 向OpenWeatherMap请求天气数据4.2 ThingSpeak 中的 ESP32 HTTP GET(更新值)在本文中,我们将介绍如使用ESP32向 ThingSpeak 和 openweathermap.org 等常用 API 发出 HTTP GET 请求。…...
PHP:json_encode和json_decode用法
json_encode 函数用于将 PHP 数据结构转换为 JSON 字符串。json_decode 函数用于将 JSON 字符串转换为 PHP 数据结构。 // 将 PHP 数据结构转换为 JSON 字符串 $data ["name" > "John","age" > 25,"city" > "New York&…...
Kafka-Java二:Spring配置kafka消息发送端的缓冲区
一、涉及到的组件概念 1.1、缓冲区 1.2、本地线程 1.3.本地线程消息推送策略 二、各组件的解释参见代码注释 // 配置消息的缓冲区/** 设置消息发送者端的缓冲区大小,如果设置了缓冲区,消息会先发送到缓冲区,可以提供发送性能* 默认大小是32…...

【ArcGIS模型构建器】05:批量为多个矢量数据添加相同的字段
本文实现借助arcgis模型构建器,实现批量为多个土地利用矢量数据添加相同的字段,例如DLMC,DLTB等。 文章目录 问题分析模型构建问题分析 有多个土地利用数据矢量图层,每个图层中有很多个图斑,现在需要给每个图层添加一个或者多个字段,如DLCM,DLBM等。 属性表如下所示: …...
坤坤的悲伤生活
描述 坤坤,这几个月来都非常悲伤,因为自己事发了,有一些问题找上了门,这个时候,有个人进献了一个阿拉丁神灯,有个灯神能够解决掉这个问题,但是有前提,必须回答出它的问题,…...

职业技术认证:《研发效能(DevOps)工程师》——开启职业发展新篇章
在互联网行业中,资质认证可以证明在该领域内的专业能力和知识水平。各种技术水平认证也是层出不穷,而考取具有公信力和权威性的认证是从业者的首选。同时,随着国内企业技术实力的提升和国家对于自主可控的重视程度不断提高,国产证…...

gin 框架出现runtime error: index out of range [0] with length 0
之前是这样的: category : c.Request.Form["type"][0] 加上这一句就变成了 fmt.Println(c.Request.FormFile("type")) category : c.Request.Form["type"][0]...

【高阶数据结构】B树
目录 1.B树 2.B树和B树的不同 3.B*树 B树较于哈希红黑树的优势:外查找:读取磁盘数据 ; B树的高度更低,对磁盘的进行I/O操作的次数更少(磁盘的性能比内存差得多); 1.B树 1.1.B树的概念&am…...
Android-Framework 应用间跳转时,提供 Android Broadcast 通知
一、环境 高通865 Android 10 二、情景 应用跳转时,通过广播发送源app的包名和目标app的包名 三、代码实现 frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java -132,6 132,14 import java.io.PrintWriter;import java.text.DateFormat;imp…...

【Javascript】函数返回值的作用
目录 返回值 中断函数 只能写在函数体里面 返回值 function a(){var b3;return b3? 4:5;} console.log(a()); 创建一个函数,给b赋值3, return b3? 4:5; 判断b是不是等于3,如果是就返回4, 如果不是就返回5 中断函数…...

蓝桥杯 Java k倍区间
前缀和的一个神奇算法,这道题暴力是遍历前缀和的差,也就是遍历所有区间和看他是不是能不能正好除尽k 这道题的技巧是将所有前缀和和k求余 按照求余的结果放在一个数组中 那么余数为0的前缀和a一定满足要求([0,a]) 余数相同的两两…...

万宾科技亮相2023中国传感器与应用技术大会,创始人CEO发表演讲
10月25日-26日,由厦门市工业和信息化局指导;中国传感器与物联网产业联盟、厦门火炬高技术产业开发区管理委员会主办的2023中国(厦门)传感器与应用技术大会暨展览会在厦门召开。本次展会聚焦传感器与储能、物联网、海洋、智慧生活、城市安全与基础设施的融合…...
#力扣:LCP 06. 拿硬币@FDDL
LCP 06. 拿硬币 - 力扣(LeetCode) 一、Java class Solution {public int minCount(int[] coins) {int ans0;for(int i0;i<coins.length;i)ans(coins[i]1)/2;return ans;} }...
【Node.js】暴露自定义响应头和预检请求的时机
1. 暴露自定义响应头 // server.js app.post(/api/user/hello, (req, res) > {res.setHeader(Access-Control-Allow-Origin, *)// 权限设置(如果有个多,用 ,隔开),暴露给前端res.setHeader(Access-Control-expose-…...
包管理工具与配置文件package.json
1,了解工程化管理核心 1.1 nodejs 理解: 在前端工程化发展中,nodejs的出现让前端开始了工程化,结束了仅静态页和切图的工作。他为前端提供了一个运行环境,让前端彻底变成了一个单独的工程,可以运行、编译…...

uni-app:解决异步请求返回值问题
可以使用 Promise 或者回调函数来处理异步请求的返回值。 方法一: Promise处理异步请求的返回值 使用 Promise 可以将异步请求的结果通过 resolve 和 reject 返回,然后通过 .then() 方法获取成功的结果,通过 .catch() 方法获取错误信息。 …...

<多线程章节七>wait() 和 notify()
💐专栏导读 本篇文章收录于多线程,也欢迎翻阅博主的其他文章,可能也会让你有不一样的收获😄 🍂JavaSE 🌷多线程 🌼数据结构 文章目录 💐专栏导读💐wait()💐no…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...