React源码解析18(9)------ 实现多节点渲染【修改beginWork和completeWork】
摘要
目前,我们已经实现了单节点的,beginWork,completeWork,diff流程。但是对于多节点的情况,比如:
<div><span></span><span></span>
</div>
这种情况,我们还没有处理,而这种JSX会被,转换为:
jsxs("div", {children: [jsx("span", {}),jsx("span", {})]
});
之前的children就直接是一个对象jsx,因为是单节点。而现在,是通过数组的方式表示。
而这一篇,主要就是对多节点的情况进行处理,所以我们要修改一下我们的index.js文件:
function App() {const [text, setText] = useState('100')const click1 = () => {setText(text + 1)}return jsx("div", {children: [jsx("div", {children: text,onClick: click1}), jsx("div", {children: ["text1","text2",jsx("span", {children: "span"})]})]})
}ReactDOM.createRoot(root).render(<App />)
1.修改beginWork流程
再次回顾,beginWork流程,主要是通过ReactElement,进行创建Filber树。而之前我们只考虑了return和child的情况,并没有将sibling考虑进去。
现在我们要将sibling这个属性,加进去,让整个Filber树更加全面,所以要修改我们的reconcileChidren方法。
之前在这个方法里面,我们判断element类型的时候,有FunctionComponent,HostComponent和HostText。现在因为有了多节点,所以element也有可能是数组。
如果是数组,我们就将第一个节点继续给parent.child。剩下的节点用sibling连接起来。
这里所有的sibling的return依旧指向parent。
function reconcileChildren(parent,element) {//其他代码。。。}else if(Array.isArray(element) && element.length > 0) {let child = reconcileChildren(parent, element.shift());let head = child;while(element.length > 0) {let sibling = reconcileChildren(parent, element.shift());sibling.return = parentchild.sibling = sibling;child = child.sibling;}return head;}//其他代码。。。
}
那再updateHostComponent中,beginWork的递归,就不能只递归child了。sibling也要递归一下:
function updateHostComponent(filberNode) {const nextChildren = filberNode.pendingProps.children;const newFilberNode = reconcileChildren(filberNode,nextChildren);filberNode.child = newFilberNode;newFilberNode.return = filberNode;beginWork(newFilberNode);if(newFilberNode.sibling) {beginWork(newFilberNode.sibling)}
}
还有一个问题就是,对于HostText类型的节点,因为不可能有child,所以在之前的递归流程中,并没有进行处理。
但是有了sibling之后,对于HostText类型的,也要对它的sibling进行递归。
function updateHostText(filberNode) {if(filberNode.sibling) {beginWork(filberNode.sibling)}
}export const beginWork = (nowFilberNode) => {switch (nowFilberNode.tag) {//其他代码。。。case HostText: {return updateHostText(nowFilberNode)}case FunctionComponent: {}default: {console.error('错误的类型')}}
}
2.处理completeWork流程
在completeWork中,我们主要就是构建离屏DOM树,然后挂载在stateNode上。对于该流程来说,我们只需要在递归的过程中,将sibling属性考虑上即可:
对于HostComponent类型:
function completeHostComponent(filberNode) {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);if(filberNode.sibling) {completeWork(filberNode.sibling)}
}
对于HostText类型:
function completeHostText(filberNode) {const content = filberNode.pendingProps;const element = document.createTextNode(content)filberNode.stateNode = elementconst parent = filberNode.return;if(parent && parent.stateNode && parent.tag === HostComponent) {parent.stateNode.appendChild(element)}if(filberNode.sibling) {completeWork(filberNode.sibling)}
}
这样,多节点的mount渲染,我们就已经处理完了。
相关文章:
React源码解析18(9)------ 实现多节点渲染【修改beginWork和completeWork】
摘要 目前,我们已经实现了单节点的,beginWork,completeWork,diff流程。但是对于多节点的情况,比如: <div><span></span><span></span> </div>这种情况,我们还没有处…...
【GUI】基于开关李雅普诺夫函数的非线性系统稳定(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Redis 缓存满了怎么办?
引言 Redis 缓存使用内存来保存数据,随着需要缓存的数据量越来越大,有限的缓存空间不可避免地会被写满。此时,应该怎么办?本篇文章接下来就来聊聊缓存满了之后的数据淘汰机制。 值得注意的是,在 Redis 中 过期策略 和…...
Grafana 安装配置教程
Grafana 安装配置教程 一、介绍二、Grafana 安装及配置2.1 下载2.2 安装2.2.1 windows安装 - 图形界面2.2.2 linux安装 - 安装脚本 三、Grafana的基本配置3.1 登录3.2 Grafana设置中文 四、grafana基本使用 一、介绍 Grafana是一个通用的可视化工具。对于Grafana而言࿰…...
【Linux】临界资源和临界区
目录 一、临界资源 二、如何实现对临界资源的互斥访问 1、互斥量 2、信号量 3、临界区 三、临界区 四、进程进入临界区的调度原则 一、临界资源 概念:临界资源是一次仅允许一个进程使用的共享资源,如全局变量等。 二、如何实现对临界资源的互斥访问 …...
拓扑排序Topological sorting/DFS C++应用例题P1113 杂务
拓扑排序 拓扑排序可以对DFS的基础上做变更从而达到想要的排序效果。因此,我们需要xy准备,vis数组记录访问状态,每一个任务都可以在dfs的过程中完成。 在使用拓扑排序方法时一些规定: 通常使用一个零时栈不会直接输出排序的节点…...
基于jenkins构建生成CICD环境
目录 一、安装配置jenkins 1、环境配置 2、软件要求 3、jdk安装(我是最小化安装,UI自带java要先删除rm -rf /usr/local/java 4、安装jenkins-2.419-1.1 二、Jenkins配置 1、修改jenkins初始密码 2、安装 Jenkins 必要插件 3、安装 Publish Over SS…...
在线图片怎么转换成PDF?在线图片转换成PDF步骤介绍
文件格式要转化不知道怎么办?想要网上下载文件格式转换软件,但是却不知道下载哪个好?今天小编小编就给大家分享一下靠谱的小圆象PDF转换器工具,想知道这款软件好不好用?在线图片怎么转换成PDF?那就进来看看吧。 在线图片怎么转换成PDF 小圆象PDF转换…...
Linux共享库基础及实例
共享库是将库函数打包成一个可执行文件,使得其在运行时可以被多个进程共享。 目标库 回顾下构建程序的一种方式: 将每个源文件编译成目标文件,再通过链接器将这些目标文件链接组成一个可执行程序。 gcc -g -c prog.c mod1.c mod2.c gcc -g …...
java八股文面试[java基础]——final 关键字作用
为什么局部内部类和匿名内部类只能访问final变量: 知识来源 【基础】final_哔哩哔哩_bilibili...
Redis 分布式锁存在什么问题 ?如何解决 ?
目录 1. 如何实现分布式锁 2. Redis 分布式锁存在什么问题 2.1 解决死锁问题 2.2 解决锁误删问题 1. 如何实现分布式锁 Redis 天生就可以作为一个分布式系统来使用,所以它实现的锁都是分布式锁。 Redis 可以通过 setnx(set if not exists)…...
n5173b是德科技keysight N5173B信号发生器
产品概述 是德科技/安捷伦N5173B EXG模拟信号发生器 当您需要平衡预算和性能时,是德科技N5173B EXG微波模拟信号发生器是经济高效的选择。它提供解决宽带滤波器、放大器、接收机等参数测试的基本信号。执行基本LO上变频或CW阻塞,低成本覆盖13、20、31.…...
React源码解析18(10)------ 实现多节点的Diff算法
摘要 在上一篇中,实现了多节点的渲染。但是之前写得diff算法,只能适用于单节点的情况,例如这种情况: <div><p><span></span></p> </div>如果对于多节点的情况: <ul><…...
Linux指令篇!
Linux 是一个广泛使用的开源操作系统,以下是一些常用的 Linux 知识点和指令: 1. 文件和目录操作: - ls:列出目录内容 - cd:切换目录 - pwd:显示当前工作目录 - mkdir:创建目录 - touch…...
Vue2学习笔记のVue组件化编程
目录 Vue组件化编程非单文件组件基本使用几个注意点组件的嵌套VueComponent一个重要的内置关系 单文件组件index.htmlmain.jsApp.vueSchool.vueStudent.vue 各位小伙伴们好呀,不知道上一篇文章你是否有收获!这篇是Vue2学习笔记第二篇,也是Vue…...
跨境电商儿童沙画办理EN71测试标准
儿童沙画就是小孩子玩的那种用彩色沙子或者彩色墨水,在有图形轮廓的纸片上去绘画,可以按照儿童沙画底板上的人物轮廓线条,动物线条,风景线条,动漫线条,去添加自己喜欢的颜色,让单调的线条变成自…...
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协议,采集温湿度值 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) {//题目要求不可以复制数组,开辟额外空间int dest -1,curr 0;for(;curr < nums.size();curr){if(nums[cu…...
数据结构入门 — 顺序表详解
前言 数据结构入门 — 顺序表详解 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 文章目录 前言一、顺序表1. 顺序表是什么2. 优缺点 二、概念及结构…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
