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

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

摘要

在上一篇中,实现了多节点的渲染。但是之前写得diff算法,只能适用于单节点的情况,例如这种情况:

<div><p><span></span></p>
</div>

如果对于多节点的情况:

<ul><li></li><li></li><li></li>
</ul>

之前实现的diff算法就不会有效果了,所以在这一篇中,我们主要实现针对于多节点的diff算法。

实现之前,我们先将index.js修改一下:

function App() {const [num, setNum] = useState(100)const click1 = () => {console.log(num);setNum(num + 1)}return num % 2 > 0 ? jsx("ul", {onClick: click1,key: 'ul',children: [jsx("li", {children: "1",key: "1"}), jsx("li", {children: "2",key: "2"}), jsx("li", {children: "3",key: "3"})]}): jsx("ul", {onClick: click1,key: 'ul',children: [jsx("li", {children: "2",key: "2"}), jsx("li", {children: "1",key: "1"}), jsx("li", {children: "3",key: "3"})]});
}ReactDOM.createRoot(root).render(<App />)

1.修改beginWork流程

在reconcileChildren方法里面,我们判断了如果element为数组的情况,就是多节点。所以我们需要在这里进行diff算法的处理。

function reconcileChildren(parent,element) {//其他代码。。。。}else if(Array.isArray(element) && element.length > 0) {const newChild = diffReconcileManyChildren(parent, element);if(newChild) {return newChild}//其他代码。。。。

所以我们的diff算法那主要是在diffReconcileManyChildren方法里面实现。

对于多节点的Diff,我们需要进行以下步骤。

  1. 创建变量lastIndex,用来标记索引
  2. 将旧的filberNode列表,转换为map结构,key为filberNode的key,value为filberNode
  3. 遍历新的element数组。
  4. 如果element.key可以在map中找到,lastIndex记录为找到的filberNode的index
  5. 如果找不到,创建新的FilberNode
  6. 继续遍历,如果又在map中找到filberNode,比较fiberNode的index和lastIndex.
  7. 如果index < lastIndex,给filberNode打上移动的标志

基于上面的步骤,实现diffReconcileManyChildren方法

function diffReconcileManyChildren(filberNode, element) {let firstChild = filberNode.child;if(!firstChild) {return;}const head = {sibling: null};const oldChildren = []while(firstChild) {oldChildren.push(firstChild);firstChild = firstChild.sibling;}const oldMap = new Map();oldChildren.forEach((item,index) => {item.index = indexif(item.key) {oldMap.set(item.key, item)}else{oldMap.set(index, item)}})let lastIndex = 0;let empty = headfor(let i=0; i<element.length; i++) {if(!element[i].key){continue;}const useFilber = oldMap.get(element[i].key);useFilber.sibling = null;if(useFilber) {if(useFilber.index < lastIndex) {useFilber.flags = 'insert'}useFilber.memoizedProps = element[i]lastIndex = useFilber.index;empty.sibling = useFilber;empty = empty.sibling;oldMap.delete(element[i].key)}else{const filberNode = new FilberNode(HostComponent, element[i].props, element[i].key) filberNode.type = element[i].typeempty.sibling = filberNode;empty = empty.sibling;}}return head.sibling;
}

经过上面的处理,beginWork流程结束,可复用的filberNode就不会重复创建。

2.修改completeWork流程

在beginWork中,可复用的节点已经被打上了insert的标志,所以在updateCompleteHsotComponent中,我们要判断是不是insert的标志,如果是,就不能无脑创建,而是通过移动DOM的位置来复用DOM。

同时,也要对同级的sibling进行递归处理。

function updateCompleteHostComponent(filberNode) {//其他代码。。。。if(element.key === filberNode.key && element.type === filberNode.type) {addPropsToDOM(filberNode.stateNode, filberNode.pendingProps);if(filberNode.flags === 'insert') {const parent = filberNode.return;parent.stateNode.insertBefore(filberNode.stateNode, filberNode.sibling?.stateNode)}//其他代码if(filberNode.sibling) {completeWork(filberNode.sibling)}
}

在对HostText的处理中,也要考虑,当前的操作是更新还是替换。

function completeHostText(filberNode) {//其他代码。。。。。if(parent && parent.stateNode && parent.tag === HostComponent) {if(!parent.stateNode) {parent.stateNode.appendChild(element);}else{parent.stateNode.replaceChildren(element);}}//其他代码。。。。
}

相关文章:

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

摘要 在上一篇中&#xff0c;实现了多节点的渲染。但是之前写得diff算法&#xff0c;只能适用于单节点的情况&#xff0c;例如这种情况&#xff1a; <div><p><span></span></p> </div>如果对于多节点的情况&#xff1a; <ul><…...

Linux指令篇!

Linux 是一个广泛使用的开源操作系统&#xff0c;以下是一些常用的 Linux 知识点和指令&#xff1a; 1. 文件和目录操作&#xff1a; - ls&#xff1a;列出目录内容 - cd&#xff1a;切换目录 - pwd&#xff1a;显示当前工作目录 - mkdir&#xff1a;创建目录 - touch…...

Vue2学习笔记のVue组件化编程

目录 Vue组件化编程非单文件组件基本使用几个注意点组件的嵌套VueComponent一个重要的内置关系 单文件组件index.htmlmain.jsApp.vueSchool.vueStudent.vue 各位小伙伴们好呀&#xff0c;不知道上一篇文章你是否有收获&#xff01;这篇是Vue2学习笔记第二篇&#xff0c;也是Vue…...

跨境电商儿童沙画办理EN71测试标准

儿童沙画就是小孩子玩的那种用彩色沙子或者彩色墨水&#xff0c;在有图形轮廓的纸片上去绘画&#xff0c;可以按照儿童沙画底板上的人物轮廓线条&#xff0c;动物线条&#xff0c;风景线条&#xff0c;动漫线条&#xff0c;去添加自己喜欢的颜色&#xff0c;让单调的线条变成自…...

chrome浏览器账号密码输入框自动填充时背景色不变

处理前 使用延时的方式解决 .login-box input,password:-webkit-autofill .login-box input,password:-webkit-autofill:hover, .login-box input,password:-webkit-autofill:focus, .login-box input,password:-webkit-autofill:active {-webkit-transition-delay: 999999…...

【ARM】Day9 cortex-A7核I2C实验(采集温湿度)

1. 2、编写IIC协议&#xff0c;采集温湿度值 iic.h #ifndef __IIC_H__ #define __IIC_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "led.h" /* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4* I2C1_S…...

【Leetcode】移动零

移动零 题目描述算法描述编程代码 链接: 移动零 题目描述 算法描述 编程代码 class Solution { public:void moveZeroes(vector<int>& nums) {//题目要求不可以复制数组&#xff0c;开辟额外空间int dest -1,curr 0;for(;curr < nums.size();curr){if(nums[cu…...

数据结构入门 — 顺序表详解

前言 数据结构入门 — 顺序表详解 博客主页链接&#xff1a;https://blog.csdn.net/m0_74014525 关注博主&#xff0c;后期持续更新系列文章 文章末尾有源码 *****感谢观看&#xff0c;希望对你有所帮助***** 文章目录 前言一、顺序表1. 顺序表是什么2. 优缺点 二、概念及结构…...

SimpleCG绘图函数(9)--绘制各种线条

一、所有线段函数概述 可填充图形绘制函数都介绍完了&#xff0c;还有一些特殊线条的绘制将在本篇进行讲解。所有特殊线条函数如下所示&#xff0c;其中还有一个区域填充函数floodfill比较特殊&#xff0c;是配合线条函数使用的&#xff1a; //绘制一系列折线段 //折线段以一组…...

RISCV 6 RISC-V加载存储指令

RISCV 6 RISC-V加载存储指令 1 RV32I Load and Store Instructions1.1 LOAD instructions1.1.1 加载指令的指令格式1.1.2 加载指令在使用时需要注意的点 1.2 STORE instructions1.2.1 存储指令的指令格式1.2.2 存储指令在使用时需要注意的点 2 RV64 Load and Store Instruction…...

木叶飞舞之【机器人ROS2】篇章_第二节、turtlebot3安装

没有真实小车的情况下&#xff0c;利用gazebo的仿真&#xff0c;操作小乌龟来学习ros2。废话不多说&#xff0c;直接上命令。 Install Gazebo sudo apt install ros-humble-gazebo-*Install Cartographer 假如前一节未安装源码版本的cartographer&#xff0c;那就安装apt版本…...

【论文阅读】自动驾驶安全的研究现状与挑战

文章目录 摘要1.引言1.1.自动驾驶安全1.2.攻击面1.3.内容和路线图 2.自动驾驶技术2.1.组成2.2.技术 3.传感器安全3.1.照相机3.2.GNSS&#xff08;全球导航系统&#xff09;/IMU&#xff08;惯性测量单元&#xff09;3.3.超声波传感器3.4.毫米波雷达3.5.激光雷达3.6.多传感器交叉…...

标签打印小工具 选择图片打印,按实际尺寸打印。可旋转图片

您可以尝试使用以下标签打印工具&#xff1a; 柯尼卡美能达标签打印机&#xff1a;功能齐全、易于使用的打印机&#xff0c;支持各种标签尺寸和类型。 赛门铁克标签打印机&#xff1a;高速打印、可靠性强的打印机&#xff0c;支持多种操作系统和软件。 齐柏林标签打印机&…...

什么是深拷贝和浅拷贝?

面试回答 在计算机内存中&#xff0c;每个对象都有一个地址&#xff0c;这个地址指向对象在内存中存储的位置。当我们使用变量引用一个对象时&#xff0c;实际上是将该对象的地址赋值给变量。因此&#xff0c;如果我们将一个对象复制到另一个变量中国&#xff0c;实际上是将对象…...

安装docker服务及docker基本操作

一、docker安装&#xff08;yum安装&#xff09; 基于centos7 1.添加docker-ce 源信息 安装依赖包&#xff08;yum-utils 提供了 yum-config-manager &#xff0c;并且 device mapper 存储驱动程序需要device-mapper-persistent-data 和 lvm2&#xff09; yum install yum-…...

【项目经验】:项目中下拉框数据太多造成页面卡顿(二)

一.项目需求 下拉框下拉列表数据是由后端返回的&#xff0c;而且他会变化&#xff0c;所以数据不是写死的而且数据量大。上一篇博客http://t.csdn.cn/sSNTa我们是用的数据懒加载的方式&#xff0c;这次我们使用远程搜索的方式解决这个问题。 二.用到的组件方法介绍 filterabl…...

Prompt本质解密及Evaluation实战(一)

一、基于evaluation的prompt使用解析 基于大模型的应用评估与传统应用程序的评估不太一样&#xff0c;特别是基于GPT系列或者生成式语言模型&#xff0c;因为模型生成的内容与传统意义上所说的内容或者标签不太一样。 以下是借用了ChatGPT官方的evaluation指南提出的对结果的具…...

linux 在系统已有python2版本下安装python3

方法一&#xff1a;使用包管理器安装 更新包索引&#xff1a; sudo apt update 安装Python3&#xff1a; sudo apt install python3 安装Python3的pip&#xff08;如果你需要&#xff09;&#xff1a; sudo apt install python3-pip 验证Python 2和3的安装&#xff1a; pyt…...

IO多路转接 ——— select、poll、epoll

select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多个文件描述符的上的事件是否就绪。 select的核心工作就是等&#xff0c;当监视的多个文件描述符中有一个或多个事件就绪时&#xff0c;select才会成功返回并将对应文件描述符的就绪…...

FPGA原理与结构——FIFO IP核原理学习

一、FIFO概述 1、FIFO的定义 FIFO是英文First-In-First-Out的缩写&#xff0c;是一种先入先出的数据缓冲器&#xff0c;与一般的存储器的区别在于没有地址线&#xff0c; 使用起来简单&#xff0c;缺点是只能顺序读写数据&#xff0c;其数据地址由内部读写指针自动加1完成&…...

64_《智能体微服务架构企业级实战教程》授权与认证之授权认证集成测试

前言 配套视频教程: 在 Bilibili课堂、CSDN课程、51CTO学堂 同步发售,提供:源码+部署脚本+文档。 bilibili课堂视频教程:智能体微服务架构企业级实战教程_哔哩哔哩_bilibili CSDN课程视频教程:智能体微服务架构企业级实战教程_在线视频教程-CSDN程序员研修院 51CTO学堂…...

服务器日志分析实战:用Python追踪HTTP 404错误并可视化异常频率

作为一名爬虫开发者或网站运维人员,服务器日志就像飞机的“黑匣子”——它记录了每个请求的来龙去脉。而404错误(页面未找到)尤其值得关注:它可能是用户输错了网址,可能是你爬虫的URL构造逻辑有漏洞,也可能是网站改版后旧的链接失效了。更严重的是,大量突然涌出的404请求…...

华硕笔记本终极性能控制指南:用G-Helper完全替代Armoury Crate

华硕笔记本终极性能控制指南&#xff1a;用G-Helper完全替代Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zen…...

收藏干货|2026 版企业 AI 落地实操指南,程序员小白入门避坑必备

如今人工智能早已脱离概念炒作阶段&#xff0c;全面扎根企业实际业务场景&#xff0c;成为技术从业者与企业管理者无法回避的发展课题。各行各业都加速布局AI赛道&#xff0c;行业心态也从初期观望试探&#xff0c;彻底转变为实打实的落地攻坚。 不少企业高层主动牵头统筹AI规划…...

NanaZip:现代Windows文件压缩问题的终极解决方案

NanaZip&#xff1a;现代Windows文件压缩问题的终极解决方案 【免费下载链接】NanaZip The 7-Zip derivative intended for the modern Windows experience 项目地址: https://gitcode.com/gh_mirrors/na/NanaZip 还在为Windows文件压缩工具界面老旧、功能单一而烦恼吗&…...

Elden Ring帧率解锁终极指南:从60帧到144+的完整教程

Elden Ring帧率解锁终极指南&#xff1a;从60帧到144的完整教程 【免费下载链接】EldenRingFpsUnlockAndMore A small utility to remove frame rate limit, change FOV, add widescreen support and more for Elden Ring 项目地址: https://gitcode.com/gh_mirrors/el/Elden…...

告别坐标点击!用Poco精准定位UI控件,让你的Airtest安卓自动化脚本更稳定

告别坐标点击&#xff01;用Poco精准定位UI控件&#xff0c;让你的Airtest安卓自动化脚本更稳定每次UI微调就导致脚本大面积失效&#xff1f;分辨率变化让精心编写的自动化测试瞬间崩溃&#xff1f;作为从坐标点击转型到控件识别的实践者&#xff0c;我深刻理解这种挫败感。三年…...

对比按量计费与Token Plan套餐的实际成本差异

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比按量计费与Token Plan套餐的实际成本差异 在构建和运营基于大模型的应用时&#xff0c;成本控制是一个核心的工程考量。Taotok…...

避坑指南:Unity动态加载模型时,TriLib插件材质丢失、缩放异常的5个常见问题解决

Unity动态加载模型避坑指南&#xff1a;TriLib插件材质丢失与缩放异常的深度解决方案当你在Unity项目中尝试使用TriLib插件动态加载外部模型时&#xff0c;是否遇到过这些令人抓狂的情况&#xff1a;模型加载后材质全部变成刺眼的粉红色&#xff0c;贴图神秘消失&#xff0c;或…...

5步完美解决Windows 10 PL2303驱动兼容性问题:完整实施方案指南

5步完美解决Windows 10 PL2303驱动兼容性问题&#xff1a;完整实施方案指南 【免费下载链接】pl2303-win10 Windows 10 driver for end-of-life PL-2303 chipsets. 项目地址: https://gitcode.com/gh_mirrors/pl/pl2303-win10 在Windows 10系统中使用PL2303 USB转串口设…...