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;
相关推荐
阿狗童鞋1 天前
React实战指南
前端·react.js·前端框架
用户298698530141 天前
React 中实现 Word 与 Markdown 双向转换的实践记录
javascript·react.js·markdown
JavaPub-rodert1 天前
开源一套 Go + React 后台管理系统,支持 RBAC 权限管理、Docker 一键部署!
react.js·golang·开源
kill5222 天前
useRef
前端·javascript·react.js
西柚小萌新2 天前
【LLM&&AI应用开发 八股文】--4.2.Agent智能体(中)
前端·javascript·react.js
Java后端的Ai之路2 天前
03_React_JSX
前端·react.js·前端框架
晴天小庭3 天前
Sael——基于Jev的AI中转站的安全风控网关,现已开源
人工智能·后端·react.js
Java后端的Ai之路3 天前
01-React基础教程
开发语言·前端·python·react.js·前端框架
流水白开3 天前
React的Virtual DOM、Diff算法和Fiber
前端·react.js