dljia
  • 前言
  • es6
    • promise
    • 箭头函数
  • http相关
    • ajax请求中contentType和dataType
    • async和defer的区别
    • cookie、session和token
    • http协议介绍
    • http缓存
    • 转发和重定向
  • js
    • 1-js深浅复制
    • 10-节流防抖
    • 11-Promise常见手写
    • 2-js函数值传递
    • 3-js原型链详解
    • 4-js基础讲解this篇
    • 5-call、apply和bind
    • 6-js中的继承
    • 7-闭包与立即执行函数
    • 8-js事件循环
    • 9-js模块化
  • react
    • React-diff
    • React-fiber
    • React组件设计规则
    • mvc与mvvm
    • react-router
    • react懒加载
    • redux
    • setState源码分析
    • webpack+react从0项目构建
  • ts
    • Typescript编程书籍导读
    • 体操基础
  • 其他
    • gitbook简易配置教程
    • gitbook转pdf电子书
  • 微前端
    • pnpm
    • qiankun
    • single-spa源码分析
    • 几种微前端架构的选型
  • 转载
    • interview-1
    • interview-2
    • interview-3
    • 经验好文
  • 项目经验
    • 23年总结
    • [Arkts 学习笔记](项目经验/Arkts 学习笔记.md)
    • Grafana插件
    • JSDoc
    • electron-builder构建的安装包,安装时通过nsis脚本自动导入注册表
    • overflow-yautohiddenscroll和overflow-xvisible组合渲染异常
    • webpack
    • 前端工程化
    • 前端性能优化思路
    • 前端性能监控工具
    • 前端架构
    • 前端登录流程
    • 前端监控原理
    • 团队管理
    • 基于node实现简单server
    • 如何对业务进行深挖
    • 如何拉齐横向
    • 如何画图
    • 如何记录
    • 组件库
Powered by GitBook
On this page

Was this helpful?

  1. react

React-fiber

Fiber 架构主要是为了解决处理非常庞大的渲染工作时,UI 上能感知到的掉帧卡顿现象,而出现。

浏览器为什么会出现掉帧

上面提到 DOM 树庞大到一定程度更新时会出现掉帧,那一定程度是多少程度?一般来说,按浏览器每秒刷新 60 次来算(即所谓的 60 FPS),当页面需要连续渲染,却在下一个 16ms 内没有渲染的情况下,就会出现掉帧的现象。也就是说,如果浏览器假如有计算执行任务阻塞了浏览器渲染,且阻塞时间超过 16ms ,就会出现卡顿掉帧被人眼所感知到。 我们都知道,JS 是单线程的,在默认情况下,JS 运算、页面绘制渲染都是运行在浏览器的主线程当中,它们之间是互斥的关系,即任何时候只能有一个占用主线程。如果 JS 运算长时间持续占用主线程,页面就没法得到及时的更新。如 1.1.1)stack reconciler 不能中途被打断 所示,只要 stack reconciler 持续使用主线程的时间,超过 16ms,页面绘制渲染就没法获得控制权,就容易出现渲染掉帧的现象。

在Fiber 中,会把一个耗时很长的任务分成很多小的任务片,每一个任务片的运行时间很短。虽然总的任务执行时间依然很长,但是在每个任务小片执行完之后,都会给其他任务一个执行机会。这样,唯一的线程就不会被独占,其他任务也能够得到执行机会。

事实上,Fiber 在设计出来后,就是需要能让 React 完成以下最主要目标:

pause work and come back to it later(暂停工作,并且能之后回到暂停的地方) assign priority to different types of work(安排不同类型工作的优先级) reuse previously completed work(之前已经处理完的工作单元,可以得到重用) abort work if it’s no longer needed(如果后续的工作不再需要做,工作可以直接被终止)

我们回到 React 设计的元概念上:

ui = f(data) 即:渲染一个 React App,其本质上就是在调用一个函数,只不过这个函数还会调用其里面的其他函数,形成调用栈。

JS 引擎自身的函数调用栈,我们无法控制,只能一条路走到黑。

Fiber 的数据结构

{
  type,
  key,
  child,
  sibling,
  return,
  pendingProps,
  memoizedProps,
  pendingWorkPriority,
  alternate,
  ...
}

type 和 key

type 跟 React Element 的 type 是相对应的,对于 composite component 来说,其类型为 function component 或者 class component 对于 host components (div, span, etc.),其类型就是对应名的字符串 key 是给 reconciler 在协调过程中,决定该 fiber 是否要复用

alternate

了解这个字段,我们需要了解 fiber 架构下的 react tree 有两棵(该版本的架构下不再提 Virtual DOM 的概念了),一棵是 current tree,另一棵是 workInProgress tree。所有的 work 都是在 workInProgress tree 的 fiber 上进行,而屏幕上呈现的是 current tree。当 react 遍历 current tree 的时候,会对 render 方法返回的 React Element 创建一个 alternate(备用)fiber,这些 fiber 节点构成了 workInProgress tree。当 react 处理完所有 work 后,会 flush workInProgress tree 到屏幕上,进而变为 current tree。 对于每个 fiber 节点的 alternate 字段来说,其用处就是保持对另一棵树对应节点的引用,current tree 上 fiber 节点的 alternate 指向 workInProgress tree 的 fiber 节点,反之亦然。

react 两颗树

current VS workInProgress current tree: 反映当前屏幕上的UI HostRoot.current; workInProgress tree: 反映下一次屏幕上的UI current.alternate; 两颗树上对应的Fiber Node 通过 alternate 字段建立联系

看了react源码以及面试得一些感受

  1. 实际上对于fibber 而言,fibber得数据结构其实就是很好得面试题,你能很好得说出fibber得结构 表明你对fibber就有一定得理解

  2. 可以问不同模式下 fibber是如何处理的。如果能答出那么大概率真的理解fibber

  3. 为什么fibber中 setState有时候是同步的有时候是异步的。原理是什么 这个原因是这样 首先fibber 的执行也就是任务调度 大概等同于一直执行一个requestIdlCallback. 回调的内容就是判断当前是否有wipFibber节点。 如果有的话,就执行调和逻辑 setState的逻辑是向当前workFibberNode的执行队列中放入多个action更新值。如果是同步的那么执行顺序是先 放多个更新值,交给fibber调度 fibber交给调和 批量更新。 如果中间有异步的action 那么就是放入更新值,交给fibber调度更新,浏览器下一个事件循环执行setState 此时继续交给fibber调度和事件更新。

参考文章

PreviousReact-diffNextReact组件设计规则

Last updated 11 months ago

Was this helpful?

React Fiber树的结构

Why Fiber
whats-fiber
完全理解React Fiber
react fiber详解