Skip to content

对应源码:packages/react-dom/src/client/ReactDOMRoot.js, packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

1. createRoot

javascript
// packages/react-dom/src/client/ReactDOMRoot.js(简化)

function createRoot(container, options) {
  const root = createContainer(container, ConcurrentRoot, ...);
  return new ReactDOMRoot(root);
}

class ReactDOMRoot {
  constructor(internalRoot) {
    this._internalRoot = internalRoot;
  }

  render(children) {
    const root = this._internalRoot;
    updateContainer(children, root, null, null);
  }

  unmount() { /* ... */ }
}

createContainer 最终调用 Reconciler 的 createFiberRoot,创建 FiberRoot 对象。

2. HostConfig:Reconciler 与 DOM 的桥梁

ReactDOM 提供的 HostConfig 包括:

javascript
// packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

const HostConfig = {
  // 创建实例
  createInstance(type, props) {
    return document.createElement(type);
  },

  // 创建文本节点
  createTextInstance(text) {
    return document.createTextNode(text);
  },

  // 追加子节点
  appendInitialChild(parent, child) {
    parent.appendChild(child);
  },

  // 插入
  insertBefore(parent, child, before) {
    parent.insertBefore(child, before);
  },

  // 删除
  removeChild(parent, child) {
    parent.removeChild(child);
  },

  // 提交属性更新(diff 在此处完成)
  commitUpdate(instance, type, oldProps, newProps) {
    updateProperties(instance, type, oldProps, newProps);
    updateFiberProps(instance, newProps);
  },

  // 提交文本更新
  commitTextUpdate(textInstance, oldText, newText) {
    textInstance.nodeValue = newText;
  },

  // ... 更多(createTextNode、appendChild、removeChild、insertBefore 等)
  // 注意:ref 的 attach/detach 不在 HostConfig 中,
  // 而是在 ReactFiberCommitWork.js 的 safelyAttachRef / safelyDetachRef 中处理
};

3. Commit 阶段的 DOM 操作

Reconciler 通过 HostConfig 间接操作 DOM,这种平台无关的设计使得同一套 Reconciler 可以适配不同的渲染目标:

commitPlacement(fiber)
  → HostConfig.appendChild 或 insertBefore

commitDeletionEffects(root, returnFiber, deletedFiber)
  → 递归调用删除子树中的 Host 节点
  → HostConfig.removeChild(最终删除 DOM 节点)

commitUpdate(fiber)
  → HostConfig.commitUpdate(instance, type, oldProps, newProps)
  → updateProperties: diff 新旧 props 并应用到 DOM

4. 初始渲染流程

createRoot(document.getElementById('root'))
  → createContainer(container, ConcurrentRoot, ...)
  → createFiberRoot()
  → 创建 FiberRoot 和 HostRoot Fiber

root.render(<App />)
  → updateContainer()
    → lane = requestUpdateLane(current)   // 不是硬编码 SyncLane
    → scheduleUpdateOnFiber(HostRoot, lane)
  → ConcurrentRoot 默认走 workLoopConcurrentByScheduler(除非 lane 为 SyncLane)
  → performUnitOfWork → beginWork(App) → beginWork(div) → ...
  → completeWork(div) → createInstance('div') → document.createElement('div')
  → appendAllChildren → div.appendChild(span)
  → commitRoot()
  → commitPlacement → root.appendChild(div)
  → 用户看到 UI

下一步

参考资料

Released under the MIT License.