createRoot解析
React 18+ 中 createRoot 函数的源码实现:
function createRoot(container, options) {
if (!isValidContainer(container)) throw Error(formatProdErrorMessage(299));
var isStrictMode = !1,
identifierPrefix = "",
onUncaughtError = defaultOnUncaughtError,
onCaughtError = defaultOnCaughtError,
onRecoverableError = defaultOnRecoverableError;
null !== options &&
void 0 !== options &&
(!0 === options.unstable_strictMode && (isStrictMode = !0),
void 0 !== options.identifierPrefix &&
(identifierPrefix = options.identifierPrefix),
void 0 !== options.onUncaughtError &&
(onUncaughtError = options.onUncaughtError),
void 0 !== options.onCaughtError && (onCaughtError = options.onCaughtError),
void 0 !== options.onRecoverableError &&
(onRecoverableError = options.onRecoverableError));
// 创建Fiber根节点
options = createFiberRoot(
container,
1,
!1,
null,
null,
isStrictMode,
identifierPrefix,
null,
onUncaughtError,
onCaughtError,
onRecoverableError,
defaultOnDefaultTransitionIndicator
);
// 标记根节点
container[internalContainerInstanceKey] = options.current;
// 绑定元素的事件监听
listenToAllSupportedEvents(container);
return new ReactDOMRoot(options);
}
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
33
34
35
36
37
38
39
40
41
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
33
34
35
36
37
38
39
40
41
# 逐步解析
# 1. 容器有效性检查
if (!isValidContainer(container)) {
throw new Error('createRoot(...): Target container is not a DOM element.');
}
1
2
3
2
3
isValidContainer 函数检查容器是否有效:
- 必须是 DOM 元素节点 (
ELEMENT_NODE= 1) - 或者是文档节点 (
DOCUMENT_NODE= 9) - 或者是文档片段节点 (
DOCUMENT_FRAGMENT_NODE= 11) - 或者是注释节点 (
COMMENT_NODE= 8) - React 18 新支持
# 2. 配置选项解析
# 支持的 options:
| 选项 | 类型 | 作用 |
|---|---|---|
unstable_strictMode | boolean | 启用严格模式(React 18 中已稳定但命名暂未变) |
identifierPrefix | string | SSR 时生成 ID 的前缀,避免多个应用冲突 |
onRecoverableError | function | 错误边界未捕获错误时的回调 |
transitionCallbacks | object | Transition 相关回调(React 19 中已变更) |
# 4. 创建 Fiber 根节点
var root = createFiberRoot(
container, // DOM 容器
ConcurrentRoot, // 模式:并发模式 1
null, // 初始 children
isStrictMode, // 是否严格模式
concurrentUpdatesByDefaultOverride, // 并发更新默认覆盖
identifierPrefix, // ID 前缀
onRecoverableError // 可恢复错误处理
);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
createFiberRoot 的作用:
- 创建 FiberRootNode(全局根节点)
- 创建 HostRootFiber(Fiber树的根)
- 初始化更新队列
- 设置各种内部属性
# 5. 标记容器
markContainerAsRoot(root.current, container);
1
建立容器与 Fiber 根的关联:
// 简化实现:
function markContainerAsRoot(hostRoot, container) {
node[internalContainerInstanceKey] = hostRoot;
}
1
2
3
4
2
3
4
# 6. 确定事件监听目标
var rootContainerElement = container.nodeType === COMMENT_NODE
? container.parentNode
: container;
1
2
3
2
3
重要:React 18 支持注释节点作为容器(用于 SSR hydration):
<!-- 客户端渲染前 -->
<div id="root">
<!--$-->
</div>
<!-- 服务器渲染后 -->
<div id="root">
<!--$-->
<div>服务端渲染的内容</div>
<!--/$-->
</div>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 7. 事件系统初始化
listenToAllSupportedEvents(rootContainerElement);
1
这是 React 事件系统的核心,实现事件委托:
function listenToAllSupportedEvents(rootContainerElement) {
// 遍历所有支持的事件类型
allNativeEvents.forEach(domEventName => {
// 非委托事件(如 scroll、load 等)
if (!nonDelegatedEvents.has(domEventName)) {
// 在捕获阶段监听
listenToNativeEvent(
domEventName,
false, // capture
rootContainerElement
);
}
// 在冒泡阶段监听
listenToNativeEvent(
domEventName,
true, // bubble
rootContainerElement
);
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
事件系统特点:
- 所有事件委托到根容器
- 提高性能,减少内存占用
- 统一处理浏览器兼容性
# 与 React 16 的差异
# React 16 的 ReactDOM.render:
ReactDOM.render(<App />, document.getElementById('root'));
// 创建 LegacyRoot(传统模式)
1
2
2
# React 17+ 的 createRoot:
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
// 创建 ConcurrentRoot(并发模式)
1
2
3
2
3
# 核心差异对比
| 特性 | Legacy Mode | Concurrent Mode |
|---|---|---|
| Fiber 根类型 | LegacyRoot (0) | ConcurrentRoot (1) |
| 渲染模式 | 同步阻塞 | 可中断并发 |
| 事件处理 | 每个元素独立监听 | 根容器事件委托 |
| 容器类型 | 仅 DOM 元素 | DOM 元素或注释节点 |
| SSR Hydration | 全有或全无 | 渐进式 hydration |
# 完整的初始化流程
// 用户调用
const root = createRoot(document.getElementById('app'), {
identifierPrefix: 'my-app-',
onRecoverableError: (error) => {
console.error('React 错误:', error);
}
});
// 内部执行流程:
1. 检查容器有效性
2. 开发环境警告
3. 解析配置选项
4. 创建 `FiberRootNode`
- `tag`: `ConcurrentRoot`
- `containerInfo`: DOM 容器
- `pendingChildren`: `null`
5. 创建 `HostRootFiber`
- `tag`: `HostRoot`
- `stateNode`: `FiberRootNode`
6. 关联容器与根节点
7. 设置事件委托
8. 返回包装对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 错误边界和可恢复错误
// 用户可提供自定义错误处理
createRoot(container, {
onRecoverableError: (error, errorInfo) => {
// 报告到监控系统
reportToErrorMonitoring(error, {
componentStack: errorInfo.componentStack
});
}
});
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# SSR Hydration 的特殊处理
// 服务器渲染时
const html = ReactDOMServer.renderToString(<App />);
// 客户端
const root = createRoot(container, {
// 如果服务器渲染时用了标识符前缀
identifierPrefix: 'myapp-'
});
// React 能正确匹配服务器和客户端节点
root.hydrate(<App />);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
这个 createRoot 函数是 React 的入口点,它建立了整个 React 应用的基础架构,包括 Fiber 树、事件系统和并发调度机制。
编辑 (opens new window)
上次更新: 2026/01/20, 09:26:42