mini-react 第二天:实现Fiber任务调度器

目的:将整棵树的render拆分成小任务避免页面卡顿

模拟卡顿:在document.append 后面加一个1个亿的 while counter

workLoop

工作机制类似于一个message queue和一个消费者

  • Message queue: 根据vdom树生成的fiber树双向链表
  • 消费者:workLoop 这个while循环
javascript 复制代码
// 对于workLoop来讲,即将执行的任务(即将处理的vdom节点)
let nextWorkOfUnit = null;


function workLoop(deadline) {
  let shouldYield = false;
  while (!shouldYield && nextWorkOfUnit) {
    nextWorkOfUnit = performWorkOfUnit(nextWorkOfUnit);

    shouldYield = deadline.timeRemaining() < 1;
  }

  requestIdleCallback(workLoop);
}


function render(el, container) {
  // 将vdom的根节点作为children,创建到 root container 上
  // 这是第一个入队的任务
  nextWorkOfUnit = {
    dom: container,  // root container dom是dom树的根节点
    props: {
      children: [el],
    },
  };
}

实现Fiber 架构

在render vdom的同时,按照双向链表结构记录当前的work节点和下一个节点

注意: fiber树仅仅是一个逻辑概念,在实现代码时,只会按照逻辑顺序逐个处理每一个节点。并不会保存一个fiber树的数据。而dom树本身就是一个树状结构。

处理一个vdom节点的核心代码逻辑

javascript 复制代码
function performWorkOfUnit(fiber) {
  // 将vdom节点转换为dom节点
  // 如果vdom节点对应的dom节点未被创建,先创建dom节点,并append到父节点的dom上
  if (!fiber.dom) {
    const dom = (fiber.dom = createDom(fiber.type));

    fiber.parent.dom.append(dom);

    updateProps(dom, fiber.props);
  }

  // 将vdom的children转换为fiber节点,并链接sibling关系
  initChildren(fiber)

  console.log(fiber);

  // 4. 返回下一个要执行的任务
  if (fiber.child) {
    return fiber.child;
  }

  if (fiber.sibling) {
    return fiber.sibling;
  }

  return fiber.parent?.sibling;
}
  • 在react v16.9.0 源代码中,关于child,sibling,parent 的处理逻辑在 /packages/react-reconciler/src/ReactFiberWorkLoop.js 中的 completeUnitOfWork 函数中。在源码中寻找构建父子兄弟节点关系的部分并不容易,但是通过源码的代码注释我们可以找到相关逻辑:
javascript 复制代码
function completeUnitOfWork(unitOfWork: Fiber): Fiber | null {
  // Attempt to complete the current unit of work, then move to the next
  // sibling. If there are no more siblings, return to the parent fiber.
  workInProgress = unitOfWork;
  do {
   ...
   // v16 源码中,parent实际命名为 return
    const returnFiber = workInProgress.return;
相关推荐
濮水大叔2 小时前
React/Next.js 生态里,有没有 CabloyJS 这样的全栈框架?
react.js·全栈·next.js
前端小D3 小时前
React Native Android 项目搭建
android·react native·react.js
Highcharts.js1 天前
Highcharts 集成到 React 或 Vue 项目中时,如何高效地使用 TypeScript技巧?
vue.js·人工智能·react.js·typescript·前端框架·highcharts
liuchangng2 天前
React 19 + Vite 6 实战:从教材 PDF 到 866 词间隔重复单词 App
前端·react.js·pdf·vite·开源项目
鸿蒙开发3 天前
Three.js 首帧卡顿排查:compileAsync 之后,为什么还会停一下?
react.js·three.js
小李科技3 天前
【性能优化】事件委托:目标定位与 React/Vue 实战
前端·vue.js·react.js·面试·性能优化·前端框架
csj503 天前
前端基础之《React(16)—Modal组件封装》
前端·react.js
ZoeLandia5 天前
React11:数据请求与 TanStack Query
前端·react.js·typescript·react
瓦瓦gogo5 天前
实习中接触前端开发后,我开始了解 React
前端·react.js·前端框架
ZoeLandia6 天前
React08:自定义 Hook
开发语言·前端·react.js·typescript