概览
在createRoot方法中提到React会调用createFiberRoot方法创建Fiber树的根节点FiberRoot以及根Fiber节点,本文主要介绍createFiberRoot这个函数。
源码解析
createFiberRoot方法
createFiberRoot是React渲染系统的核心初始化函数,负责:
- 创建应用根容器 :实例化
FiberRootNode作为整个 React 应用的顶层容器 - 初始化渲染模式:设置并发模式/传统模式,以及严格模式标记
- 建立
Fiber树结构 :创建HostRootFiber作为Fiber树的根节点 - 设置双向引用 :建立
FiberRootNode和HostRootFiber之间的相互引用 - 初始化缓存系统:设置 React 18+ 的缓存机制
- 配置错误处理:设置各类错误的回调函数
- 准备更新队列:初始化状态更新管理机制
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渲染的核心函数,设置FiberRoot 和 HostRootFiber的双向引用以及初始化更新队列等关键操作。