React Fiber 浅谈

React Fiber

背景

React 为了描述组件状态和Dom的关系,采用虚拟DOM来表示真实DOM。
每个组件在每次渲染时会创建一个新的Virtual DOM,React会把新的Virtual DOM树与现有的相比较,然后将一系列转变应用于真实DOM。

在 React 15 的版本中,虚拟 Dom 采用 Stack 架构实现,diff 更新的过程是 同步循环递归,这就导致只有所有的 组件 更新之后,才会让出主进程进行 Dom 渲染。

虚拟 Dom 树如果直接更新,当组件非常多时,给数据更新的 diff 带来了很大压力。如果 js占据主线程去做比较,渲染线程便无法做其他工作,用户的交互得不到响应,所以便出现了react fiber。

什么是 Fiber

按照名词解释,这是一种数据结构(也可叫执行单元),将虚拟 Dom Tree 转变为 可支持·断点遍历重启 的 链表(单链表树结构)。

按照动词解释,这是协程,React Fiber 把一次更新过程碎片化,细致控制虚拟 Dom 更新 和 渲染 Dom 展示这些操作的执行顺序。

基于碎片化更新的过程,每次执行完单个碎片更新,就会把主线程交给 React 其他模块,来处理其他紧急任务。如果没有紧急任务,那就继续更新。

工作原理

Fiber 节点保存了 Dom 节点,Fiber 树和 Dom 树互相呼应。

通过判断当前执行帧空闲空间,来选择执行对应优先级的执行任务,在当前帧结束前再次判断是否有剩余时间和任务来支持执行,没有则执行浏览器渲染任务,并循环这一过程来最大化提升渲染效率。

利用requestAnimationFrame来确保每一帧执行的任务。

利用requestIdleCallback 来指定执行哪些低优先级的任务。如果遇到超过正常帧的任务,执行完毕后就需要立即归还控制权,并使用 requestIdleCallback 来再次申请下一次更新的时间片。requestIdleCallback 会给 callback 传递IdleDeadline 来判断任务的操作状态。

  • timeRamining():用来判断用户代理预计还剩余多少闲置时间。
  • didTimeout:用来判断当前的回调函数是否因超时而被执行。

双缓存 Fiber 树

  1. 基于渲染内容的 CurrentFiber Tree
  2. 内存中实时构建的 WorkInProgress Fiber Tree(节点之间通过 altermnate 属性连接)

根节点通过指针 current 在不同的 FiberTree 和 RootFiber 之间切换,完成 current Fiber Tree 指向的切换。

更新内容在 WorkInProgress Fiber Tree 构建完成后,经由 Renderer 渲染到页面上后,根节点的 current 指向 WorkInProgress Fiber 树,基于互相呼应的原理,这棵 WorkInProgress Fiber Tree 此时变成了 CurrentTree。当下一次 State 更新时,构建新的 WorkInProgress Fiber Tree, 然后再次执行上述操作,便完成了 Tree 的 替换,也就是 Dom 的更新

Render 阶段

此处的 Render 并非指浏览器渲染页面,而是虚拟 Dom 和 真实 Dom 的 Diff 过程,并进行变化的内容标记收集。**Render 是一个可以被打断的过程。 ** 在该阶段构建一棵Fiber tree,产生和虚拟 Dom 一一对应的任务,并且产出最后的更新 List(Effect List)。

收集 Effect List

  1. 如果当前节点需要更新,则使用对应tag标记当前节点状态(props, state, context等);
  2. 为每个子节点创建fiber。
    1. 并为 需要更新的 Fiber 添加两个属性:
      • firstEffect:指向第一个有变更的子fiber。
      • lastEffect:指向最后一个有变更的子fiber。

而我们需要收集的就是中间nextEffect,最终形成一个单链表。

  1. 如果没有产生child fiber,则结束该节点,把effect list归并到return,把此节点的兄弟节点作为下一个遍历节点;否则把子节点作为下一个遍历节点;
  2. 如果有剩余时间,则开始下一个节点,否则等下一次主线程空闲再开始下一个节点;
  3. 如果没有下一个节点了,进入pendingCommit状态,此时effect list收集完毕,结束。

Commit 阶段

Commit 阶段会将根据 EffectList 将上述操作中标记需要变更的 Fiber 更新到 DOM 树上,此阶段为了确保 UI 更新的连续性,是不可中断的过程。

到这里,整个 Fiber 的 刷新和更新过程就完成了。

总结

Fiber 是基于碎片化任务和和交替变更浏览器控制权,来达到更好的更新效果。其通过双缓存机制,在其 Render 阶段比较 虚拟 Dom 树和 真实 Dom,并进行节点变更标记和收集变更依赖,在 Commit 阶段更新 被标记 Fiber 节点到真实 Dom 树完成整个更新和刷新流程。

相关推荐
华玥作者8 小时前
[特殊字符] VitePress 对接 Algolia AI 问答(DocSearch + AI Search)完整实战(下)
前端·人工智能·ai
Mr Xu_8 小时前
告别冗长 switch-case:Vue 项目中基于映射表的优雅路由数据匹配方案
前端·javascript·vue.js
前端摸鱼匠8 小时前
Vue 3 的toRefs保持响应性:讲解toRefs在解构响应式对象时的作用
前端·javascript·vue.js·前端框架·ecmascript
lang201509288 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
好家伙VCC9 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
摘星编程10 小时前
React Native鸿蒙版:Image图片占位符
react native·react.js·harmonyos
未来之窗软件服务10 小时前
未来之窗昭和仙君(六十五)Vue与跨地区多部门开发—东方仙盟练气
前端·javascript·vue.js·仙盟创梦ide·东方仙盟·昭和仙君
嘿起屁儿整10 小时前
面试点(网络层面)
前端·网络
VT.馒头10 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
phltxy11 小时前
Vue 核心特性实战指南:指令、样式绑定、计算属性与侦听器
前端·javascript·vue.js