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;
相关推荐
薛定谔的算法6 分钟前
《虚拟 DOM 与 Diff 算法:用 1500 字把它讲成“人话”》
前端·react.js·前端框架
鹏多多12 分钟前
前端项目eslint配置选项详细解析
前端·vue.js·react.js
知识分享小能手1 小时前
React学习教程,从入门到精通,React 使用属性(Props)创建组件语法知识点与案例详解(15)
前端·javascript·vue.js·学习·react.js·前端框架·vue
牧羊狼的狼6 小时前
React 中的 HOC 和 Hooks
前端·javascript·react.js·hooks·高阶组件·hoc
知识分享小能手8 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
魔云连洲8 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
资深前端之路11 小时前
react 面试题 react 有什么特点?
前端·react.js·面试·前端框架
秋秋小事11 小时前
React Hooks useContext
前端·javascript·react.js
还有多远.13 小时前
jsBridge接入流程
前端·javascript·vue.js·react.js
hj5914_前端新手15 小时前
React 基础 - useState、useContext/createContext
前端·react.js