react渲染流程是怎样的

整体流程:

react的核心可以用ui=fn(state)来表示,更详细可以用:

javascript 复制代码
const state = reconcile(update);
const UI = commit(state);

上面的fn可以分为如下一个部分:

  • Scheduler(调度器): 调度任务,排序优先级,让优先级高的任务先进行reconcile
  • Reconciler(协调器): 生成Fiber对象,找出哪些节点发生了改变,并打上不同的Flags(旧版本 react叫Tag),著名的diff算法也是在这个阶段中执行的;
  • Renderer(渲染器): 将Reconciler中打好标签的节点渲染到视图上

调度器

在react16之前,采用的是stack架构,所有任务只能同步进行,无法被打断,导致浏览器出现丢帧情况,表现出卡顿,react为了解决这个问题,从16之后进行了两大更新:

  • 引入Fiber
  • 新增了Scheduler
    Scheduler在浏览器原生API中实际是有类似API的,reqestIleCallback虽然每一帧的绘制时间约为16.66ms,但是若屏幕没有刷新,那么浏览器会安排长度为50ms左右的空闲时间。
    为什么是50ms?
    据研究,100ms以内用户感觉都是瞬时发生的,不会感受到延迟感,因此将空闲时间设置为50,浏览器仍然还剩余50ms。
    后期react打算重新开发这个Scheduler,这意味这调度器不仅仅是在react中使用,凡是有任务调度的项目都可以使用Scheduler。

协调器

协调器是render阶段的第二个阶段,类组件或者函数组件本身就是在这个阶段被调用的。

根据Scheduler调度结果的不同,协调器起点可能是不同的;

performSyncWorkOnRoot(同步更新流程)

会执行workLoopSync这个方法

performConcurrentWorkOnRoot(并发更新流程)

javascript 复制代码
function workLoopSync (){
  while(workProgress != null){
     performUnitOfWork(workProgress)
}
}
javascript 复制代码
function workLoopConcurrentSync (){
  while(workProgress != null && shouldYield()){
     performConcurrentWorkOnRoot(workProgress)
  }
}

新的架构使用Fiber对象来描述dom结构,最终需要形成一棵Fiber tree,不过这棵Fiber树是通过链表形式串联在一起的。

workInProgress代表的是当前的FiberNode

performUnitOfWork方法创建下一个FiberNode,并且还会将已经创建的FiberNode连接起来(child、return、sibling),从而形成一棵链表结构的Fiber tree。

若workInProgress为空,则表示没有下一个FiberNode,也就说整颗Fiber Tree已经构建完毕。

上面两个方法的区别是是否调用了shouldYield方法,该方法表明了是否可以中断。

performUnitOfWork在创建下一个FiberNode 时候,整体分为以下两大块:

  • 递阶段
  • 归阶段

递阶段

从HostRootFiber开始按照深度优先(先找到最底层)原则进行遍历,遍历到的每一个FiberNode执行beginWork方法,该方法会根据传入的FiberNode创建下一级的FiberNode,此时可能存在两种情况:

  • 下一级只有一个元素,beginWork方法会创建对应的FiberNode,并且与workInProgress连接
  • 下一级有多个元素,beginWork方法会依次创建所有的子FiberNode并且通过与subling连接到一起,每个FiberNode也会和workInProgress连接。
javascript 复制代码
<ul>
<li></li>
<li></li>
<li></li>
</ul>

此时会创建3个li对应的FiberNode,连接情况如下:

所有的子Fiber依次连接

Li0Fiber.sibling = Li1Fiber

Li1Fiber.sibling = Li2Fiber

子Fiber还要和父Fiber连接

Li0Fiber.return = UlFiber

Li1Fiber.return = UlFiber

Li2Fiber.return = UlFiber

由于采用的是深度优先原则,因此无法再往下走的时候,会走入归阶段。

归阶段

归阶段会调用completeWork方法来处理FiberNode,做副作用的收集。

当某个FiberNode执行完了completeWork,若存在兄弟元素,就会进入到兄弟元素的递阶段,若不存在兄弟元素,就会进入父FiberNode的归阶段。

我们来看一张图:

渲染器

Renderer工作阶段称为commit阶段,该阶段会将各种副作用commit到宿主环境的UI中。

相较于之前的render阶段可以被打断,commit阶段一旦开始就会同步执行直到完成渲染工作。

整个渲染过程可以分为三个子阶段:

beforeMutation

Mutation

Layout

相关推荐
用户47949283569157 小时前
改了CSS刷新没反应-你可能不懂HTTP缓存
前端·javascript·面试
还好还好不是吗8 小时前
老项目改造 vue-cli 2.6 升级 rsbuild 提升开发效率300% upupup!!!
前端·性能优化
sumAll8 小时前
别再手动对齐矩形了!这个开源神器让 AI 帮你画架构图 (Next-AI-Draw-IO 体验)
前端·人工智能·next.js
OpenTiny社区8 小时前
2025OpenTiny星光ShowTime!年度贡献者征集启动!
前端·vue.js·低代码
wangan0948 小时前
不带圆圈的二叉树
java·前端·javascript
狗哥哥8 小时前
从零到一:打造企业级 Vue 3 高性能表格组件的设计哲学与实践
前端·vue.js·架构
疯狂平头哥8 小时前
微信小程序真机预览-数字不等宽如何解决
前端
Drift_Dream8 小时前
前端趣味交互:如何精准判断鼠标从哪个方向进入元素?
前端
hqk8 小时前
鸿蒙ArkUI:状态管理、应用结构、路由全解析
android·前端·harmonyos
米思特儿林8 小时前
NuxtImage 配置上传目录配置
前端