react fiber的实现过程

298 阅读1分钟

1.把react elment转化成fiber结构

  1. 链表结构遍历
  2. 使用nextworkUnit保存当前fiber,使其能够异步的遍历组件树中的fiber节点,用requestIdleCallback包裹workLoop
let wipRoot = null;
let nextUnitOfwork = null
// 采用非递归的迭代方法实现深度遍历,使每次处理unit可以在浏览器空闲时进行
function performUnitOfWork(wip) {
  // 处理unit
  // 虚拟dom 生成 原生dom
  // 子节点变成fiber结构,并和父节点组成链表结构
  // 1.unit的child变成unitchildren的第一个child,
  // 2.其他的child变成第一个child的sliber
  // 结构上变成深度遍历(先序)后的链表

  //判断是什么类型的节点,不同节点处理方式不同,根据type来判断,str,funciton
  const { type } = wip;
  if (isStr(type)) {
    updateHostComponent(wip)
  } else if (isFn(type)) {
    updateFunctionComponent(wip)
  } else {
    updateFragmentComponent(wip)
  }

  if (wip.child) {
    return wip.child
  }
  let next = wip;
  while (next) {
    if (next.sibling) {
      return next.sibling
    }
    next = next.return;
  }
  return null
}

function workLoop(IdleDeadline) {
  while (nextUnitOfwork && IdleDeadline.timeRemaining() > 0) {
    nextUnitOfwork = performUnitOfWork(nextUnitOfwork)
  }
  if (!nextUnitOfwork && wipRoot) {
    // commit  sliberDom - render 深度遍历 一次性加载全部
    console.log(wipRoot)
    commitRoot(wipRoot)
  }
}

2.递归commit

function commitWorker(wip) {
  if (!wip) return;

  // 1。提交自己
  const { stateNode } = wip;
  // fiber可能没有dom节点,比如函数组件类组件
  let parentNode = getParentNode(wip.return); //wip.return.stateNode; // 父dom节点
  if (stateNode) {
    parentNode.appendChild(stateNode);
  }
  // 2、 子节点
  commitWorker(wip.child);
  // 3.兄弟
  commitWorker(wip.sibling);
}

3.fiber结构

export function createFiber(vnode, returnFiber) {
  const newFiber = {
    // 节点类型
    type: vnode.type,
    // 标记节点在当前层级下的唯一性
    key: vnode.key,
    // 属性
    props: vnode.props,
    // 原生标签是dom节点,类组件是类实例
    stateNode: null,
    // 第一个子节点
    child: null,
    // 父节点
    return: returnFiber,
    // 下一个兄弟节点
    sibling: null,
    alternate: null,
    flags: Placement,
  }
  return newFiber
}