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;
相关推荐
前端若水7 小时前
会话管理:创建、切换、删除对话历史
前端·人工智能·python·react.js
放下华子我只抽RuiKe58 小时前
React 从入门到生产(四):自定义 Hook
前端·javascript·人工智能·深度学习·react.js·自然语言处理·前端框架
从文处安13 小时前
「前端何去何从」React Router:让单页应用有多页的体验
前端·react.js
whuhewei15 小时前
React diff算法为什么是DFS,不是BFS
算法·react.js·深度优先
从文处安15 小时前
「前端何去何从」混乱到有序的状态管理: Reducer 与 Context
前端·react.js
爱滑雪的码农17 小时前
React Native 完整开发全流程(从零到上线)
javascript·react native·react.js
Maimai1080818 小时前
React 多步骤表单工程化落地:从 Zod Schema、React Hook Form 到 Zustand 持久化
前端·javascript·react.js·前端框架·状态模式
Maimai1080818 小时前
React Query + Zustand 正确结合方式:不要把接口数据复制进 Store
前端·javascript·react.js·前端框架·web3·状态模式
Maimai1080818 小时前
Zustand 项目落地:从全局状态、Store 拆分到真实业务封装
前端·react.js·前端框架·状态模式
放下华子我只抽RuiKe518 小时前
React 从入门到生产(五):状态管理选型
前端·javascript·人工智能·深度学习·react.js·前端框架·ecmascript