Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 《React源码》笔记
  • React-reconciler
东流
2026-01-20
目录

updateContainerImpl方法更新容器

# 概览

在ReactDOMRoot的render和unmount方法中均调用了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));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# createUpdate

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

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

# 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);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# scheduleUpdateOnFiber

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

# entangleTransitions

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

  1. 将当前更新与正在进行的过渡更新纠缠
  2. 确保过渡更新的正确顺序
  3. 处理并发模式下的更新冲突
编辑 (opens new window)
上次更新: 2026/01/24, 10:05:32
最近更新
01
Scheduler任务调度执行
02-02
02
Scheduler的任务优先级
01-28
03
Scheduler中的最小二叉堆
01-26
更多文章>
Theme by Vdoing | Copyright © 2024-2026 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式