首页 > 其他分享 >React原理之React整体渲染流程

React原理之React整体渲染流程

时间:2024-08-09 16:26:05浏览次数:11  
标签:Fiber 渲染 流程 DOM React 阶段 Scheduler Reconciler

前置知识:深度优先搜索(DFS)、Fiber 节点

在上一篇 React原理篇之 React 整体架构解读中,提到了 Fiber 架构中的几个核心概念:

  • Scheduler(调度器):根据任务的优先级安排任务执行顺序。
  • Reconciler(协调器):根据新旧虚拟 DOM 树的差异确定需要更新的部分。
  • Renderer(渲染器):将更新的虚拟 DOM 转换为实际的 UI 输出。

这三个组件共同工作提供了 React 的高效和灵活的渲染机制,那么他们具体是怎么渲染的呢?

React 的渲染的两个阶段

React 的渲染流程分为两个阶段:

  • render 阶段:Reconciler 的工作阶段,这个阶段会调用组件的 render 方法
  • commit 阶段:Renderer 的工作阶段,可以类比 git commit 提交,这个阶段会渲染具体的 UI。

在这里插入图片描述

先以这个两个阶段的整体工作流程举例:

export default function App() {
	const [count, setCount] = useState(0);

	const handleIncrement = () => {
		setCount((prevCount) => prevCount + 1);
	};
	return (
		<div>
			<h3>{count}</h3>
			<button onClick={handleIncrement}>点击加一</button>
		</div>
	);
}

在这里插入图片描述

如上图所示,当用户点击按钮更新 count,Scheduler 先进行任务的协调,当 Scheduler 调度完成后,将任务交给 Reconciler,Reconciler 就需要计算出新的 UI,最后就由 Renderer 同步进行渲染更新操作。

Scheduler 和 Reconciler 的工作流程是可以随时被以下原因中断:

  • 有其他更高优先级的任务需要执行
  • 当前的 time slice 没有剩余的时间
  • 发生了其他错误

Scheduler 和 Reconciler 的的工作是在内存里进行的,不会更新用户界面,因此即使工作流程反复被中断,用户也不会看到更新不完全的 UI。

由于 Scheduler 和 Reconciler 都是平台无关的,所以React为他们单独发了一个包react-Reconciler

调度器 Scheduler

上篇文章提到,Fiber 和 Scheduler 都是 React16 引入的。Scheduler 是用来根据任务的优先级安排任务执行顺序的。

其实部分浏览器的原生 API 已经实现了,即requestIdleCallback

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback

但是由于 浏览器兼容性触发频率受很多因素影响而不稳定 等问题,React放弃使用浏览器原生的 API,React实现了功能更完备的requestIdleCallbackPolyfill,即Scheduler。除了在空闲时触发回调的功能外,Scheduler还提供了多种调度优先级供任务设置。

另外,Scheduler是独立于React的库,可以用来实现任务调度,而不只是在 React 中使用。

注:Polyfill 是指用于在旧版本浏览器中实现新标准 API 的代码填充(或称垫片)。它通常用于解决旧版本浏览器不支持新特性或 API 的问题。

协调器 Reconciler 与 Render 阶段

Reconciler 实现可中断的循环

Reconciler 根据新旧虚拟 DOM 树的差异确定需要更新的部分。

上一篇文章说到,在 React15 中Reconciler是递归处理虚拟 DOM 的。而 React16 中,更新工作从递归变成了可以中断的循环过程。

  • 每次循环都会调用shouldYield判断当前是否有剩余时间。如果当前浏览器帧没有剩余时间,shouldYield会中止循环,直到浏览器有空闲时间后再继续遍历。
  • Reconciler 与 Renderer 不再是交替工作。当 Scheduler 将任务交给 Reconciler 后, Reconciler 会为变化的虚拟 DOM 打上代表增/删/更新的标记,整个 Scheduler 与 Reconciler 的工作都在内存中进行。只有当所有组件都完成 Reconciler 的工作,才会统一交给 Renderer。

Render 阶段

类组件或者函数组件本身就是在 render 阶段被调用的。在源码中,render 阶段开始于performSyncWorkOnRootperformConcurrentWorkOnRoot方法的调用,这取决于本次更新是同步更新还是异步更新。

  1. performSyncWorkOnRoot:同步模式

  2. performConcurrentWorkOnRoot:并发模式

// performSyncWorkOnRoot会调用该方法
function workLoopSync() {
	while (workInProgress !== null) {
		performUnitOfWork(workInProgress);
	}
}

// performConcurrentWorkOnRoot会调用该方法
function workLoopConcurrent() {
	while (workInProgress !== null && !shouldYield()) {
		performUnitOfWork(workInProgress);
	}
}

对于以上代码的注释:

workInProgress : 当前已创建的workInProgress fiber,即在内存中构建的Fiber树(具体 fiber 双缓存相关后面文章细讲)

shouldYield: 如果当前浏览器帧没有剩余时间,shouldYield会中止循环,直到浏览器有空闲时间后再继续遍历。(可以看到上面两种方法的区别是是否调用 shouldYield)

performUnitOfWork: 创建下一个Fiber节点并赋值给workInProgress,并将workInProgress与已创建的Fiber节点连接起来构成Fiber树

可以看到上面两种方法主要都是在执行performUnitOfWork,下面我们详细看一下performUnitOfWork

performUnitOfWork 方法

performUnitOfWork 方法的工作流程可以分为两个阶段:“ 递 ” 和 “ 归 ”。

“递阶段 —— beginWork”

作用:传入当前Fiber节点,创建子Fiber节点

首先从rootFiber开始向下深度优先遍历。为遍历到的每个Fiber节点调用beginWork方法(此方法后续详细介绍),该方法会根据传入的Fiber节点创建子Fiber节点,并将这两个Fiber节点连接起来。

当遍历到叶子节点(即没有子组件的组件)时就会进入“归”阶段。

“归阶段 —— complateWork”

作用:收集一些副作用。

在“归”阶段调用 completeWork 处理Fiber节点,主要是收集一些副作用。(此方法后续详细介绍)

当某个Fiber节点执行完completeWork,如果其存在同级Fiber节点(即fiber.sibling !== null),会进入其同级Fiber的“递”阶段。

如果不存在同级Fiber,会进入父级Fiber的“归”阶段。

“递”和“归”阶段会交错执行直到“归”到rootFiber。至此,render阶段的工作就结束了。

图示 “ 递 ” 和 “ 归 ”

先看一个简单的:

在这里插入图片描述

稍复杂的 fiber 节点。注意 beginWork 和 complateWork 的顺序:
在这里插入图片描述

渲染器 Renderer 与 commit 阶段

render 阶段完成后,开启commit阶段工作流程,Renderer 在此阶段工作。

与 render 阶段可以被打断不同的是,commit 阶段是不可以被打断的,一旦开始就会同步执行直到完成渲染工作。

渲染器 Renderer 的工作主要就是将各种副作用(flags 表示)commit 到宿主环境的 UI 中。整个阶段可以分为三个阶段,分别是 BeforeMutation 阶段、Mutation 阶段和 Layout 阶段

  1. before mutation 阶段(执行DOM操作前):一些准备工作,如处理 DOM 节点渲染/删除后的 autoFocusblur 逻辑、触发getSnapshotBeforeUpdate生命周期方法、调度useEffect
  2. mutation 阶段(执行DOM操作):React 根据调和阶段的计算结果执行 DOM 的增删改操作。
  3. layout 阶段(执行DOM操作后):执行一些可能需要最终的 DOM 结构信息才能完成的工作,比如测量 DOM 元素的尺寸和位置。

注意:在before mutation阶段之前和layout阶段之后还有一些额外工作,涉及到比如useEffect的触发、优先级相关的重置、ref的绑定/解绑。

标签:Fiber,渲染,流程,DOM,React,阶段,Scheduler,Reconciler
From: https://blog.csdn.net/jydchudq/article/details/141054957

相关文章

  • vue2 bpmnjs流程图
    原作者gitee地址:gitclonehttps://gitee.com/cjy2353/best-vue-bpmnjs.git"bpmn-js":"^17.9.2","vue":"^2.6.11",node-v"v14.17.6"使用:`importBpmnfrom'com/Bpmn'components:{Bpmn,},`bpmn组件如下:......
  • 团体标准制定与发布有哪些流程?需要满足什么条件?
    百问百答 ▷▷▷Q&A标准化知识问答第3期 »»»»团体标准的制定与发布前言|在上一期的内容中,我们介绍了团体标准的原则和价值,今天,我们接着向下,了解团体标准的制定与发布。团体标准的制定与发布是一个涉及多方参与和复杂程序的过程。通过本期内容,我们将揭示这一过程的......
  • 【面试高频,必知必会】OpenGL渲染流程
    ......
  • (算法)图像渲染————<递归>
    1.题⽬链接:733.图像渲染2.题⽬描述:3.算法思路:可以利⽤「深搜」或者「宽搜」,遍历到与该点相连的所有「像素相同的点」,然后将其修改成指定的像素即可。递归函数设计:•参数:a.原始矩阵;b.当前所在的位置;c.需要修改成的颜⾊。•函数体:a.先将该位置的颜⾊......
  • 深中通道元宇宙启航!3DCAT实时云渲染助力沉浸式体验深中通道
    2024年6月30日上午,深圳至中山跨江通道(以下简称“深中通道”)开通活动在深中通道西人工岛举行。10时50分许,深中通道正式开通。下午3时已通车试运营。粤港澳大湾区超级工程深中通道(图源新华网)01 幻海云桥:沉浸式体验的新纪元就在开通的同一天,中山日报社与3DCAT、广东涌态信息等......
  • react渲染列表中的key的作用
    这个key首先是只在渲染数组列表的时候会用到。比如经常遇到的 如上没有key的话,会报一个错,那么,我们可不可以使用数组的index作为下标呢?答案是不推荐。因为在数组项的顺序在插入、删除或者重新排序等操作中会发生改变,此时把索引作为key可能会产生一些微妙的bug。像下面这种......
  • 轮换挑选图片,补充 es6的对象写法,uniapp使用,class和style,条件渲染,列表渲染,input
    Ⅰ轮换挑选图片【一】方式一<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scriptsrc="./js2/vue.js"></script></head><body>......
  • react中封装Echarts
    下载npxcreate-react-appmy-echarts创建公共组件importReact,{useState,useEffect,useMemo}from'react';import*asechartsfrom"echarts";constEChartsComponent=({option})=>{const[echartsInstance,setEchartsInstance]=u......
  • 重塑购车体验,实时云渲染赋能东风日产探路云看车新体验
    在科技日新月异的今天,汽车行业正经历着前所未有的深刻变革。随着互联网+、大数据、人工智能等新兴技术的深度融合,汽车营销策略也迎来了从传统展示到数字化体验的跨越。消费者的购车习惯逐渐倾向于线上互动与深度体验,希望在线上获得线下同等的体验,迫使汽车制造商及经销商重新审......
  • 1392、STM32单片机温湿度检测阈值报警4个继电器加4个负载风扇等无线蓝牙远程(程序+原
    毕设帮助、开题指导、技术解答(有偿)见文未 目录方案选择单片机的选择显示器选择方案一、设计功能二、实物图三、原理图四、程序源码五、PCB图资料包括:需要完整的资料可以点击下面的名片加下我,找我要资源压缩包的百度网盘下载地址及提取码。方案选择单片机的选......