源码分析之React中createFiberRoot方法创建Fiber根节点

概览

createRoot方法中提到React会调用createFiberRoot方法创建Fiber树的根节点FiberRoot以及根Fiber节点,本文主要介绍createFiberRoot这个函数。

源码解析

createFiberRoot方法

createFiberRoot是React渲染系统的核心初始化函数,负责:

  1. 创建应用根容器 :实例化 FiberRootNode作为整个 React 应用的顶层容器
  2. 初始化渲染模式:设置并发模式/传统模式,以及严格模式标记
  3. 建立 Fiber 树结构 :创建 HostRootFiber作为 Fiber 树的根节点
  4. 设置双向引用 :建立 FiberRootNodeHostRootFiber之间的相互引用
  5. 初始化缓存系统:设置 React 18+ 的缓存机制
  6. 配置错误处理:设置各类错误的回调函数
  7. 准备更新队列:初始化状态更新管理机制
js 复制代码
function createFiberRoot(
  containerInfo, // 容器信息
  tag, //1, 根节点类型 
  hydrate, // false,表示客户端渲染
  initialChildren, // 初始子元素
  hydrationCallbacks, // 水合回调
  isStrictMode, // 是否严格模式
  identifierPrefix, // 用于生成React唯一ID的前缀
  formState,// 表单状态
  onUncaughtError, //未捕获错误回调
  onCaughtError, // 已捕获错误回调
  onRecoverableError, // 可恢复错误回调
  onDefaultTransitionIndicator //默认过渡指示回调
) {
  // 创建FiberRootNode实例,
  // containerInfo会管理所有Fiber节点的状态
  // containerInfo是整个React应用的根容器
  containerInfo = new FiberRootNode(
    containerInfo,// 宿主容器
    tag, // 根节点类型
    hydrate, // 是否水合
    identifierPrefix, // ID前缀
    onUncaughtError, // 未捕获错误回调
    onCaughtError, // 已捕获错误回调
    onRecoverableError, // 可恢复错误回调
    onDefaultTransitionIndicator, // 过渡指示器
    formState // 表单状态
  );
  // 设置根节点的模式标记 1表示concurrentRoot 并发模式  
  tag = 1;
  // 判断是否启用严格模式,若启用则添加严格模式标记
  !0 === isStrictMode && (tag |= 24);
  // 创建HostRootFiber 即根Fiber节点 
  isStrictMode = createFiberImplClass(3, null, null, tag); // 3表示HostRoot类型
  // 建立FiberRoot 和 HostRootFiber的双向引用
  // FiberRoot.current指向当前渲染的Fiber树
  containerInfo.current = isStrictMode; 
  // HostRootFiber.stateNode指向FiberRoot
  isStrictMode.stateNode = containerInfo;

  // 创建并初始化缓存系统
  tag = createCache();
  tag.refCount++; // 增加缓存引用计数

  // 将缓存挂载到FiberRoot
  containerInfo.pooledCache = tag;
  // 再次增加引用计数,FiberRoot和HostFiber都持有缓存
  tag.refCount++;
  
  // 初始化HostRootFiber,即当前渲染树的memoizedState
  // 存储初始渲染的React元素和状态
  isStrictMode.memoizedState = {
    element: initialChildren, // 初始子节点
    isDehydrated: hydrate, // 是否处于脱水状态 (SSR)
    cache: tag // 缓存引用
  };

  // 初始化HostRootFiber的更新队列:用于管理组件的状态更新
  initializeUpdateQueue(isStrictMode);

  // 返回FiberRootNode实例
  return containerInfo;
}

cache缓存系统

cache的实现如下:

js 复制代码
/**
 * AbortController的兼容性实现,主要用于React的sSuspense和并发渲染中的异步操作取消
 */
var AbortControllerLocal =
    "undefined" !== typeof AbortController
      ? AbortController
      : function () {
          // 存储所有事件监听器 
          var listeners = [],
          // 创建 signal 对象,模拟原生的AbortSignal
            signal = (this.signal = {
              aborted: !1, // 是否已取消,初始化为false
              // 添加事件监听器
              addEventListener: function (type, listener) {
                listeners.push(listener);
              }
            });
          // abort 方法:取消所有监听的操作  
          this.abort = function () {
            // 设置已取消状态
            signal.aborted = !0;
            // 触发所有监听器
            listeners.forEach(function (listener) {
              return listener();
            });
          };
        }

/**
 * 创建缓存对象的工厂函数
 */
function createCache() {
  return {
    controller: new AbortControllerLocal(), // AbortController实例
    data: new Map(), // 缓存数据
    refCount: 0 // 引用计数器
  };
}

initializeUpdateQueue

initializeUpdateQueue方法用于初始化Fiber节点的更新队列,其实现如下:

js 复制代码
function initializeUpdateQueue(fiber) {
  fiber.updateQueue = {
    // 基础状态:当前已提交的状态,用于计算新状态时的基准
    baseState: fiber.memoizedState,
    
    // 基础更新链表:上次渲染时尚未处理的更新
    firstBaseUpdate: null, // 链表头
    lastBaseUpdate: null, // 链表尾
    // 共享队列:存储本次渲染周期中新添加的更新,是一个环形链表,便于在末尾添加新更新
    shared: { 
      pending: null, // 指向环形链表的最后一个节点
      lanes: 0, // Lanes模型中车道优先级
      hiddenCallbacks: null // 隐藏的回调函数
    },
    // 回调函数列表:更新完成后需要执行的回调
    callbacks: null
  };
}

总结

createFiberRoot方法是React渲染的核心函数,设置FiberRootHostRootFiber的双向引用以及初始化更新队列等关键操作。

相关推荐
Jinuss3 小时前
源码分析之React中ReactDOMRoot实现
前端·javascript·react.js
摘星编程4 小时前
React Native鸿蒙版:React Query无限滚动
javascript·react native·react.js
web守墓人4 小时前
【前端】vue3的指令
前端
想起你的日子4 小时前
EFCore之Code First
前端·.netcore
框架图4 小时前
Html语法
前端·html
深耕AI5 小时前
【wordpress系列教程】07 网站迁移与备份
运维·服务器·前端·数据库
月空MoonSky5 小时前
解决使用Notepad++出现异型字或者繁体字体问题
java·javascript·notepad++
joan_855 小时前
input禁止自动填充
前端·elementui·vue