React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React updateContainerImpl更新容器

React中updateContainerImpl方法更新容器源码解析

作者:Jinuss

updateContainerImpl方法是React中更新容器的核心方法,负责创建和调度更新,通过createUpdate方法创建更新对象,并通过enqueueUpdate方法将其加入Fiber节点的更新队列,本文介绍React中updateContainerImpl方法更新容器源码分析,感兴趣的朋友一起看看吧

概览

ReactDOMRootrenderunmount方法中均调用了updateContainerImpl方法,该方法是React中更新容器的核心方法,负责创建和调度更新。

源码分析

updateContainerImpl

updateContainerImpl方法源码实现如下:

function updateContainerImpl(
  rootFiber, //根Fiber节点
  lane, // 更新优先级
  element, //要渲染的React元素
  container, // Fiber根节点容器
  parentComponent, // 父组件
  callback // 更新完成后的回调函数
) {
  // 获取子树的上下文,会返回一个空对象
  parentComponent = getContextForSubtree(parentComponent);
  // 若Fiber根节点容器上下文为空,则设置其为获取到的上下文(空对象);否则设置待处理的上下文为空对象
  null === container.context
    ? (container.context = parentComponent)
    : (container.pendingContext = parentComponent);
  // 根据优先级车道创键更新对象  
  container = createUpdate(lane);
  // 将要渲染的React元素作为更新对像的载荷
  container.payload = { element: element };

  // 若回调未定义,则设为null,否则保留原值
  callback = void 0 === callback ? null : callback;
  // 若回调不为null,则将其设为更新对象的callback属性值
  null !== callback && (container.callback = callback);
  
  // 将更新对象添加到Fiber节点的更新队列,并获取FiberRoot
  element = enqueueUpdate(rootFiber, container, lane);

  // 判断 若返回的更新对象不为null,则调度更新
  null !== element &&
    (scheduleUpdateOnFiber(element, rootFiber, lane),
    entangleTransitions(element, rootFiber, lane));
}

createUpdate

createUpdate接受一个参数车道优先级(lane),返回一个更新对象,其对象类型为UpdateUpdate会被放入更新队列中等待调度执行,其优先级为参数lanetagUpdateState:0,其实现如下:

function createUpdate(lane){
  return {
    lane: lane,  // 更新优先级
    tag: UpdateState, // 其值为1 ,表示更新类型
    payload: null, // 更新载荷
    callback: null, // 回调函数
    next: null // 指向下一个更新
  }
}

enqueueUpdate

enqueueUpdate方法用于将更新对象加入Fiber节点的更新队列,其源码实现如下:

function enqueueUpdate(fiber, update, lane) {
  // 获取Fiber节点上的更新队列updateQueue
  var updateQueue = fiber.updateQueue;
  // 若更新队列为空,则返回null,此时Fiber节点已被卸载
  if (null === updateQueue) return null;
  // 获取共享队列
  updateQueue = updateQueue.shared;

  // 检查是否是渲染更新阶段
  if (0 !== (executionContext & 2)) {
    // 获取共享队列的最后一个节点
    var pending = updateQueue.pending;
    // 判断最后一个节点是否为空
    null === pending
      ? (update.next = update) // 将更新对象update的next指向自身
      : ((update.next = pending.next), (pending.next = update)); //否则将更新对象的next指向最后一个节点的next,并且将最后一个节点的next指向更新对象,即将更新对象插入到环形链表的末尾
    // 更新pending指针  
    updateQueue.pending = update;
    // 从Fiber节点中获取FiberRoot
    update = getRootForUpdatedFiber(fiber);
    // 标记fiber节点中的优先级
    markUpdateLaneFromFiberToRoot(fiber, null, lane);
    // 最后返回FiberRoot
    return update;
  }
  // 若不是渲染更新阶段,则依次执行enqueueUpdate$1,getRootForUpdatedFiber,最后返回getRootForUpdatedFiber的结果FiberRoot
  // 调用enqueueUpdate$1方法就是将相关参数放到并发队列concurrentQueues中
  enqueueUpdate$1(fiber, updateQueue, update, lane);
  return getRootForUpdatedFiber(fiber);
}

getRootForUpdatedFiber

Fiber节点的return始终是指向父节点,因此通过不断追溯return可以找到根节点;

function getRootForUpdatedFiber(sourceFiber) {
  // 判断某计数器,暂且不提
  if (50 < nestedUpdateCount)
    throw (
      ((nestedUpdateCount = 0),
      (rootWithNestedUpdates = null),
      Error(formatProdErrorMessage(185)))
    );
  for (var parent = sourceFiber.return; null !== parent; )
    (sourceFiber = parent), (parent = sourceFiber.return);
  
  // 判断当前Fiber节点的根节点类型是否为HostRoot,若是,则返回其DOM元素,否则返回null
  return 3 === sourceFiber.tag ? sourceFiber.stateNode : null;
}

scheduleUpdateOnFiber

调用enqueueUpdate方法更新相关队列后,会拿到FiberRoot,若FiberRoot不为null,则调用scheduleUpdateOnFiber进行调度更新。

entangleTransitions

entangleTranslations方法用于纠缠过渡更新,主要有3个作用:

  1. 将当前更新与正在进行的过渡更新纠缠
  2. 确保过渡更新的正确顺序
  3. 处理并发模式下的更新冲突

到此这篇关于React中updateContainerImpl方法更新容器源码解析的文章就介绍到这了,更多相关React updateContainerImpl更新容器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文