React16源码: React中的resetChildExpirationTime的源码实现

resetChildExpirationTime


1 )概述

  • completeUnitOfWork 当中,有一步比较重要的一个操作,就是重置 childExpirationTime
  • childExpirationTime 是非常重要的一个时间节点,它用来记录某一个节点的子树当中,目前优先级最高的那个更新
  • 整个应用的调度过程当中使用的都是root节点,在 scheduleWork 的时候,即便我们创建更新的那个节点,是我们写的某一个组件
  • 但最终要先找到那一个root节点,然后再把它放到调度队列当中,因为会有这样的一个情况的存在
  • 所以我们对于一个 reactApp 来说,它某一个节点下面可能是会存在非常多的一个子树的
  • 每棵子树它创建的不同的任务,它的 expirationTime 都会不一样的
  • 通过 childExpirationTime 来集中,最终可以在 root 上面能够快速的找到整个应用当中优先级最高的那个任务
  • 举个例子,假设同时在 Input 和 List 两个组件内都去创建了一个异步的更新,创建这个异步的更新的过程当中
  • 假设,Input的 ExpirationTime 优先级比较高,List 的 expirationTime 优先级比较少
  • 对于div节点来说,它记录的是Input节点的 expirationTime, 因为它的优先级比较高
  • 对于div来说,它如果下一个任务要去更新,它的优先级肯定是先更新 Input,而不会先更新 List
  • 对于 RootFiber 和 App来说,因为它们的child只有div, 所以它们记录的会是 div 上面指定的那个优先级最高的 expirationTime
  • 所以说 childExpirationTime 对于有分叉的点来说是非常重要的, 它可以记录不同的子树所创建的不同的更新
  • 如果我们的分叉变得越来越多,有非常多个的时候,那么用这种方式来记录它的效率明显是会是更高一点的
  • 对于这个情况下,如果我 Input 这个更新已经执行完了,它上面已经没有 expirationTime,因为它没有任务要去更新了
  • 对于div来说,这个时候如果它还是认为这个Input它之前的 expirationTime 是最高优先级的话,那就不对了,之后的更新可能就会有出现问题
  • 所以对于div这个节点,我们执行了 completeUnitOfWork 之后,要去更新它的 childExpirationTime
  • 对于每一个节点都是一样的, 在上述这个例子里面,特别重要的一点就是 div, div 要更新,那么它上面的节点都是要更新的
  • 因为它们之前记录的都是 div 记录的那个值,所以,它们执行 completeUnitOfWork 的时候,也都要去做相同的操作

2 )源码

定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L989

对应到代码里面,来看在 completeUnitOfWork 里面,我们这边执行完了 completeWork
马上会执行 resetChildExpirationTime 那么这个方法它具体做了什么呢?

function resetChildExpirationTime(workInProgress: Fiber,renderTime: ExpirationTime,
) {// 首先判断 renderTime ,就是当前正在执行更新的那一个优先级对应的 expirationTime// 如果它不等于never,并且 workInProgress.childExpirationTime 等于 Never// 也就是说 workInProgress 就是我们当前节点的子节点优先级最高的那个任务是never// 就是永远不会更新到的并且我们现在也不是正在执行,never,就是永远不会更新到的那些节点的更新// 说明我们这边根本就不需要做任何的操作,所以我们直接return就可以了if (renderTime !== Never && workInProgress.childExpirationTime === Never) {// The children of this component are hidden. Don't bubble their// expiration times.return;}let newChildExpirationTime = NoWork;// Bubble up the earliest expiration time.// 跳过这个if, 直接到 elseif (enableProfilerTimer && workInProgress.mode & ProfileMode) {// We're in profiling mode.// Let's use this same traversal to update the render durations.let actualDuration = workInProgress.actualDuration;let treeBaseDuration = workInProgress.selfBaseDuration;// When a fiber is cloned, its actualDuration is reset to 0.// This value will only be updated if work is done on the fiber (i.e. it doesn't bailout).// When work is done, it should bubble to the parent's actualDuration.// If the fiber has not been cloned though, (meaning no work was done),// Then this value will reflect the amount of time spent working on a previous render.// In that case it should not bubble.// We determine whether it was cloned by comparing the child pointer.const shouldBubbleActualDurations =workInProgress.alternate === null ||workInProgress.child !== workInProgress.alternate.child;let child = workInProgress.child;while (child !== null) {const childUpdateExpirationTime = child.expirationTime;const childChildExpirationTime = child.childExpirationTime;if (childUpdateExpirationTime > newChildExpirationTime) {newChildExpirationTime = childUpdateExpirationTime;}if (childChildExpirationTime > newChildExpirationTime) {newChildExpirationTime = childChildExpirationTime;}if (shouldBubbleActualDurations) {actualDuration += child.actualDuration;}treeBaseDuration += child.treeBaseDuration;child = child.sibling;}workInProgress.actualDuration = actualDuration;workInProgress.treeBaseDuration = treeBaseDuration;} else {// 这边主要是有一个 while循环, 这个while循环它首先使用的是 workInProgress.child// 它就是我们当前节点的child,然后获取child的 expirationTime 以及 childChildExpirationTime// child.expirationTime 是它自身它所创建的更新对应的 expirationTime// 而 child.childExpirationTime 是child的子树里面任何几个节点它所创建的更新所对应的优先级最高的 expirationTimelet child = workInProgress.child;while (child !== null) {// 为什么这边要用这两个值?因为我们没有办法直接拿到当前节点它所有子树最高优先级的点// 只能是通过去遍历它的所有的第一层的子节点以及每个子节点它的 childExpirationTime// 因为我们这个 completeUnitOfWork 是由底往上去更新的一个过程// 那么由底往上更新的过程,就会每一个节点都会对应这个操作// 对应的这个操作之后,它肯定就是每一个节点都会更新到优先级最高的那个 expirationTimeconst childUpdateExpirationTime = child.expirationTime;const childChildExpirationTime = child.childExpirationTime;// 接下来进行判断更新if (childUpdateExpirationTime > newChildExpirationTime) {newChildExpirationTime = childUpdateExpirationTime;}if (childChildExpirationTime > newChildExpirationTime) {newChildExpirationTime = childChildExpirationTime;}// 下一个节点child = child.sibling;}}workInProgress.childExpirationTime = newChildExpirationTime;
}
  • 以上注释写在代码里,简单来说
    • 就是在每一次 complete 一个节点之后就要
    • 去重设它的 childExpirationTime 的一个过程

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

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

相关文章

git 本地分支提交远程分支

在日常开发中,我们常常遇到这样的场景,本地有个分支名字:developtemp,远程有个分支origin/develop,两个分支没有关联关系,而且分支名字不同,此时想提交代码。 //先拉取远程分支代码 git pull o…

html中根元素以及根元素字体的含义

在 HTML 中&#xff0c;根元素是指 <html> 标签&#xff0c;可以使用 CSS 来设置根元素的字体大小。根元素的字体大小会影响整个页面的文本内容&#xff0c;默认情况下&#xff0c;根元素的字体大小是浏览器默认的大小。 要设置根元素的字体大小&#xff0c;你可以使用 …

如何进行技术选型

关键步骤 进行技术选型时通常会考虑的几个关键步骤&#xff1a; 1. 理解项目需求 业务需求&#xff1a;明确业务目标和需求是技术选型的起点。了解项目的目标、预期成果以及业务方面的限制。技术需求&#xff1a;确定技术上的必要条件&#xff0c;比如性能、可扩展性、安全性…

大数据基础设施搭建 - Redis

一、上传压缩包 二、解压压缩包 [mallmall software]$ tar -zxvf redis-6.2.1.tar.gz -C /opt/module/三、查看gcc是否安装 redis是用c写的&#xff0c;因此安装redis需要c语言的编译环境&#xff0c;即需要安装gcc [mallmall module]$ gcc -v四、编译 [mallmall ~]$ cd /op…

C++提高编程——STL:string容器、vector容器

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…

数据结构:堆与堆排序

目录 堆的定义&#xff1a; 堆的实现&#xff1a; 堆的元素插入&#xff1a; 堆元素删除&#xff1a; 堆初始化与销毁&#xff1a; 堆排序&#xff1a; 堆的定义&#xff1a; 堆是一种完全二叉树&#xff0c;完全二叉树定义如下&#xff1a; 一棵深度为k的有n个结点的二…

ffmpeg使用及java操作

1.文档 官网: FFmpeg 官方使用文档: ffmpeg Documentation 中文简介: https://www.cnblogs.com/leisure_chn/p/10297002.html 函数及时间: ffmpeg日记1011-过滤器-语法高阶&#xff0c;逻辑&#xff0c;函数使用_ffmpeg gte(t,2)-CSDN博客 java集成ffmpeg: SpringBoot集成f…

科技云报道:金融大模型落地,还需跨越几重山?

科技云报道原创。 时至今日&#xff0c;大模型的狂欢盛宴仍在持续&#xff0c;而金融行业得益于数据密集且有强劲的数字化基础&#xff0c;从一众场景中脱颖而出。 越来越多的公司开始布局金融行业大模型&#xff0c;无论是乐信、奇富科技、度小满、蚂蚁这样的金融科技公司&a…

深度学习如何弄懂那些难懂的数学公式?是否需要学习数学?

经过1~2年的学习&#xff0c;我觉得还是需要数学有一定认识&#xff0c;重新捡起高等数学、概率与数理、线代等这几本&#xff0c;起码基本微分方程、求导、对数、最小损失等等还是会用到。 下面给出几个链接&#xff0c;可以用于平时充电学习。 知乎上的&#xff1a; 机器学…

计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

git merge和git rebase区别

具体详情 具体常见如下&#xff0c;假设有master和change分支&#xff0c;从同一个节点分裂&#xff0c;随后各自进行了两次提交commit以及修改。随后即为change想合并到master分支中&#xff0c;但是直接git commit和git push是不成功的&#xff0c;因为分支冲突了【master以…

上位机图像处理和嵌入式模块部署(流程)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;传统图像处理的方法&#xff0c;一般就是pccamera的处理方式。camera本身只是提供基本的raw data数据&#xff0c;所有的…

基于ADAS的车道线检测算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 图像预处理 4.2 车道线特征提取 4.3 车道线跟踪 5.完整工程文件 1.课题概述 基于ADAS的车道线检测算法,通过hough变换和边缘检测方法提取视频样板中的车道线&#xff0c;然后根据车道线的弯曲情况…

《Python数据分析技术栈》第06章使用 Pandas 准备数据 13 分组和汇总 Grouping and aggregation

13 分组和汇总 Grouping and aggregation 《Python数据分析技术栈》第06章使用 Pandas 准备数据 13 分组和汇总 Grouping and aggregation Aggregation is the process of summarizing a group of values into a single value. 聚合是将一组值汇总为一个值的过程。 Hadley …

【 CSS 】精灵图、字体图标、CSS 三角、常用布局技巧

1. 精灵图&#xff08;重点&#xff09; 1.1 为何需要精灵图 一个网页中往往会应用很多小的背景图像作为修饰&#xff0c;当网页中的图像过多时&#xff0c;服务器就会频繁地接收和发送请求图片&#xff0c;造成服务器请求压力过大&#xff0c;这将大大降低页面的加载速度。 …

Linux/Mac 命令行工具 tree 开发项目结构可以不用截图了 更方便 更清晰 更全

tree 是一个命令行工具&#xff0c;用于以树形结构显示文件系统目录的内容。它可用于列出指定目录下的所有文件和子目录&#xff0c;以及它们的层次关系。tree 命令在许多操作系统中都可用&#xff0c;包括Unix、Linux和macOS。 效果如下&#xff1a; 一、安装 linux # De…

「Git」config 配置

Git 会自动跟踪是 谁 修改了项目&#xff0c;哪怕只是其中的一个字符&#xff0c;所以&#xff0c;Git需要配置用户的用户名以及邮箱地址。因此&#xff0c;在开始 Git 管理之前&#xff0c;我们可以先把 Git的用户设置配置一下【非必需&#xff0c;如果没有配置&#xff0c;Gi…

Prometheus+Grafana监控Mysql数据库

Promethues Prometheus https://prometheus.io Prometheus是一个开源的服务监控系统&#xff0c;它负责采集和存储应用的监控指标数据&#xff0c;并以可视化的方式进行展示&#xff0c;以便于用户实时掌握系统的运行情况&#xff0c;并对异常进行检测。因此&#xff0c;如何…

Ansible剧本playbooks

playbooks概述 Ansible剧本&#xff08;playbook&#xff09;是用于配置、部署和管理被控节点的一种描述文件。通过编写详细的剧本描述和执行其中的任务&#xff08;tasks&#xff09;&#xff0c;可以使远程主机达到预期的状态。剧本由一个或多个"play"组成的列表构…

Spring Boot3整合knife4j(swagger3)

目录 1.前置条件 2.导依赖 3.配置 1.前置条件 已经初始化好一个spring boot项目且版本为3X&#xff0c;项目可正常启动。 作者版本为3.2.2最新版 2.导依赖 knife4j官网&#xff1a; Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j (xiaominfo.com)http…