当前位置: 首页 > news >正文

React源码解析18(8)------ 实现单节点的Diff算法

摘要

经过之前的几篇文章,我们已经实现了一个可以进行更新渲染的假React。但是如果我们把我们的jsx修改成这样:

function App() {const [age, setAge] = useState(20)const click = function() {setAge(age + 1)}return age % 2 === 0 ? jsx("div", {key: 'div1',children: jsx("span", {key: 'span',children: 'div1',onClick: click})}) : jsx("div", {key: 'div1',children: jsx("span", {key: 'span',children: 'div2',onClick: click})})
}ReactDOM.createRoot(root).render(<App />)

虽然页面的效果是正确的。但对于两个jsx,二者的区别仅仅是span标签里面的内容不同。
但是在程序里面,我们是相当于每次都重新beginWork,重新的创建Filber树,重新的创建真实DOM。
而对于这里div和span标签,它没有任何的改变,我们是否可以用一种优化策略,从而对旧资源进行利用呢? 所以Diff由此而来。

这一篇先只说单节点的Diff,因为目前还没实现带有sibling的情况。

1.修改beginWork

我们回顾一下在beginWork里面干了什么。在将jsx转换为ReactElement后,我们会通过beginWork来构建一颗Filber树。
那如果,对于可复用的FilberNode,我们是否可以不去创建,直接复用呢?
可以的,那对于React来说,什么节点是可复用的呢:

如果旧的FilberNode和新的ReactElement
key相同,type相同。
那么就是可以复用的。

所以在beginWork中的reconcileChildren方法里,如果我们发现上面的情况,我们就不会创建新的FilberNode。

function reconcileChildren(parent,element) {const newChild = diffReconcileChildren(parent, element);if(newChild) {return newChild}//其他代码。。。return filberNode
}

2.实现diffReconcileChildren方法

该方法接受两个参数,第一个是父节点,第二个是新的ReactElement。

(1)我们要先拿到父节点的child,比较child和element的key和type。
(2)将element保存在child的memoizedState里面。
(3)然后其他逻辑和reconcileChildren里的一样即可。
(4)直接返回child。

function diffReconcileChildren(filberNode, element) {const child = filberNode.child;if(child && child.key && child.type) {if(child.key === element.key && child.type === child.type) {child.memoizedProps = element;child.pendingProps = element.props;if(child.tag === HostText) {child.pendingProps = element}return child;}}
}

这里为什么要将element保存在memoizedState里面,是因为虽然节点没有改变,但是子节点可能有改变,或者属性会有改变。所以要在后面的completeWork里进行处理。

3.修改completeWork

经过上面的处理后,FilberNode不会无脑的重复创建,而是复用了。而completeWork的工作,主要是创建真实DOM,挂载在FilberNode的stateNode上。

所以在completeWork中,也不能无脑的创建真实DOM,而是也要判断是否是可复用的。

export const completeWork = (filberNode) => {const tag = filberNode.tagswitch (tag) {case HostComponent: {if(filberNode.stateNode !== null){//更新updateCompleteHostComponent(filberNode)}else{completeHostComponent(filberNode)}break;}//其他代码。。。。}
}

所以在对HostComponent的处理上,如果发现不是mount阶段,就要判断是否需要复用旧的。

4.实现updateCompleteHostComponent方法

在该方法中,我们接受filberNode。同时我们可以拿到它的memoizedState(在beginWork中传过来的)。

再判断一下key和type,如果依旧相同,那么说明是可复用的。我们直接不创建新的DOM即可。

function updateCompleteHostComponent(filberNode) {const element = filberNode.memoizedProps;if(element.key === filberNode.key && element.type === filberNode.type) {addPropsToDOM(filberNode.stateNode, filberNode.pendingProps)}else{const type = filberNode.type;const element = document.createElement(type);addPropsToDOM(element, filberNode.pendingProps)filberNode.stateNode = element;const parent = filberNode.return;if(parent && parent.stateNode && parent.tag === HostComponent) {parent.stateNode.appendChild(element)}}completeWork(filberNode.child)
}

addPropsToDOM方法是我们在实现事件机制的时候,需要调用的方法。

OK,这样我们就实现了单节点的Diff算法。

相关文章:

React源码解析18(8)------ 实现单节点的Diff算法

摘要 经过之前的几篇文章&#xff0c;我们已经实现了一个可以进行更新渲染的假React。但是如果我们把我们的jsx修改成这样&#xff1a; function App() {const [age, setAge] useState(20)const click function() {setAge(age 1)}return age % 2 0 ? jsx("div"…...

并查集路径压缩(Java 实例代码)

目录 并查集路径压缩 Java 实例代码 UnionFind3.java 文件代码&#xff1a; 并查集路径压缩 并查集里的 find 函数里可以进行路径压缩&#xff0c;是为了更快速的查找一个点的根节点。对于一个集合树来说&#xff0c;它的根节点下面可以依附着许多的节点&#xff0c;因此&am…...

Educational Codeforces Round 153 (Rated for Div. 2)

A.我直接构造&#xff08;&#xff08;&#xff08;&#xff09;&#xff09;&#xff09;&#xff09;和&#xff08;&#xff09;&#xff08;&#xff09;&#xff08;&#xff09;这种了&#xff0c;因为这两种都很简便&#xff0c;只有&#xff08;&#xff09;和&#xf…...

分布式 | 如何搭建 DBLE 的 JVM 指标监控系统

本篇文章采用 Docker 方式搭建 Grafana Prometheus 实现对 DBLE 的 JVM 相关指标的监控系统。 作者&#xff1a;文韵涵 爱可生 DBLE 团队开发成员&#xff0c;主要负责 DBLE 需求开发&#xff0c;故障排查和社区问题解答。 本文来源&#xff1a;原创投稿 爱可生开源社区出品&a…...

下线40万辆,欧拉汽车推出2023款好猫尊荣型和GT木兰版

欧拉汽车是中国新能源汽车制造商&#xff0c;成立于2018年。截至目前&#xff0c;已经下线了40万辆整车&#xff0c;可见其在市场的影响力和生产实力。为了庆祝这一里程碑&#xff0c;欧拉汽车推出了品牌书《欧拉将爱进行到底》&#xff0c;在其中讲述了欧拉汽车的发展历程和未…...

【Python】使用python解析someip报文,以someip格式打印报文

文章目录 1.安装scapy库2.解析someip格式报文3.示例 1.安装scapy库 使用 pip 安装 scapy 第三方库&#xff0c;打开 cmd&#xff0c;输入以下命令&#xff1a; pip install scapy出现如图所示&#xff0c;表示安装成功&#xff1a; 2.解析someip格式报文 要解析someip格式报…...

C#与西门子PLC1500的ModbusTcp服务器通信2--ModbusTcp协议

Modbus TCP是近年来越来越流行的工业控制系统通信协议之一&#xff0c;与其他通信协议相比&#xff0c;Modbus TCP通信速度快、可靠性高、兼容性强、适用于模拟或数字量信号的传输&#xff0c;阅读本文前你必须比较熟悉Modbus协议&#xff0c;了解tcp网络。 一、什么是Modbus …...

SpringBoot + MyBatis-Plus构建树形结构的几种方式

1. 树形结构 树形结构&#xff0c;是指&#xff1a;数据元素之间的关系像一颗树的数据结构。由树根延伸出多个树杈 它具有以下特点&#xff1a; 每个节点都只有有限个子节点或无子节点&#xff1b;没有父节点的节点称为根节点&#xff1b;每一个非根节点有且只有一个父节点&a…...

linux vscode 下开发

linux vscode 下开发 javajdk插件查看调用层次 java jdk 各种JAVA JDK的镜像分发 编程宝库 - 技术改变世界 jdk 镜像 ubuntu22.04 安装 # Linux x64 64位 jdk-8u351-linux-x64.tar.gztar -zxf jdk-8u351-linux-x64.tar.gz mv jdk1.8.0_351 jdk8/ vim ~/.pr…...

【工具】python代码编辑器--PyCharm下载安装和介绍

PyCharm是一种Python IDE(集成开发环境),由JetBrains打造。它带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、项目管理、代码跳转、智能提示、自动完成、单元测试、版本控制等。此外,PyCharm还提供了一些高级功能,以用于支持Django框…...

SpringBoot第44讲:SpringBoot集成Redis - Redis分布式锁的实现之Jedis(setNXPX+Lua)

SpringBoot第44讲&#xff1a;SpringBoot集成Redis - Redis分布式锁的实现之Jedis(setNXPXLua) Redis实际使用场景最为常用的还有通过Redis实现分布式锁。本文是SpringBoot第44讲&#xff0c;主要介绍Redis实现分布式锁 文章目录 SpringBoot第44讲&#xff1a;SpringBoot集成Re…...

STM32F4X USART串口使用

STM32F4X USART串口使用 串口概念起始位波特率数据位停止位校验位串口间接线 STM32F4串口使用步骤GPIO引脚复用函数串口初始化函数串口例程 串口概念 串口是MCU与外部通信的重要通信接口&#xff0c;也是MCU在开发过程中的调试利器。串口通信有几个重要的参数&#xff0c;分别…...

python实现两个字符串比对差异点

一:代码实现 import difflib, re# 比较两个文本差异点 def compare_text_index(text1, text2):# 创建SequenceMatcher对象matcher = difflib.SequenceMatcher(a=text1, b=text2)# 获取差异报告diff_report = matcher.get_opcodes()# 检查差异报告中是否存在关键词错误for tag…...

SQLite数据库实现数据增删改查

当前文章介绍的设计的主要功能是利用 SQLite 数据库实现宠物投喂器上传数据的存储&#xff0c;并且支持数据的增删改查操作。其中&#xff0c;宠物投喂器上传的数据包括投喂间隔时间、水温、剩余重量等参数。 实现功能&#xff1a; 创建 SQLite 数据库表&#xff0c;用于存储宠…...

【Golang系统开发】搜索引擎(2) 压缩词典

写在前面 这篇文章我们就给出一系列的数据结构&#xff0c;使得词典能达到越来越高的压缩比。当然&#xff0c;和倒排索引记录表的大小相比&#xff0c;词典只占据了非常小的空间。那么为什么要对词典进行压缩呢&#xff1f; 这是因为决定信息检索系统的查询响应时间的一个重…...

clickhouse修改默认密码

1.明文密码 vim /etc/clickhouse-server/users.xml找到下面的语句,增加明文密码 <password>123456789</password> 2. sha256密码 # echo -n 123456789 | openssl dgst -sha256 (stdin) 15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 修改…...

基于java在线捐赠系统设计与实现

摘要 近年来&#xff0c;随着网络的快速发展&#xff0c;由于网络的开放性和便利性&#xff0c;具有广阔的发展前景。 本文设计并实现了医药捐赠系统。通过分析确定由两个不同的用户组成&#xff0c;每个用户具有不同的功能。它还可以帮助用户在线求助、申请项目、发表留言等&a…...

【前端】vscode javascript 代码片段失效问题解决

1. 文件--首选项--用户代码片段-vue.json : 添加 // { // // Place your global snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and // // description. Add comma separated ids of the languages where the snippet is app…...

AE-卡通人物解说动画视频的制作

目录 1.导入卡通人物图片和音频文件 2.新建合成 3.在卡通人物图片上添加效果和表达式 4.在音频文件上添加效果和表达式 5.将卡通人物中的 CC Split2 中分割1 表达式链接到滑块中 6.卡通人物根据音频文件自动匹配口型。 AE制作卡通人物解说视频&#xff0c;卡通人物口型根据…...

Linux 查看日志

在 Linux 中&#xff0c;内核日志使用 printk 函数进行输出。你可以通过以下方法查看 printk 的日志&#xff1a; 使用 dmesg 命令&#xff1a; dmesg 这个命令会显示内核环缓冲区中的日志消息&#xff0c;包括使用 printk 输出的消息。你可以通过滚动浏览输出来查看完整的日志…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...