Skip to content

第18章 设计模式与架构决策

本章要点

  • React 源码中 10 个核心设计模式的识别与深度剖析:从 Observer 到 Visitor 的工程实践
  • 从 Class 到 Hooks 到 Compiler:三次 API 范式跃迁背后的设计哲学演变
  • Algebraic Effects 与 Prepack:React 团队探索过又放弃的技术方案考古
  • React vs Vue vs Svelte vs Solid:四大框架从响应式模型到编译策略的终极架构对比
  • React 的技术决策方法论:为什么"选择不做什么"比"选择做什么"更重要
  • React 下一个十年的技术趋势:从运行时框架到全栈编译器平台

写完前面十七章,我们已经从 JSX 编译、Fiber 架构、调度器、Reconciliation、Commit 阶段、Hooks 实现、并发模式、Server Components、React Compiler 等各个维度,完成了对 React 19 内核的全面解剖。如果把前面的章节比作"显微镜"——逐行逐函数地观察 React 机体的每一个细胞,那么本章我们需要换一种工具:望远镜

站在足够远的距离回望 React 的源码,你会发现一个令人惊叹的事实:在那些看似复杂的实现细节之下,存在着一组反复出现的设计模式。它们不是教科书上的学术练习,而是 React 团队在十余年工程实践中,面对真实约束做出的真实选择。同时,React 的发展史本身就是一部"技术决策史"——每一次重大版本更新,都意味着一次架构哲学的重新审视。理解这些决策的"为什么",远比记住它们的"是什么"更有价值。

本章是全书的收官之章。我们将从设计模式、API 设计哲学、技术考古、框架对比、未来展望五个维度,为你构建一幅 React 架构决策的全景图。这不仅是对前面所有章节的一次高维度总结,更是帮助你建立框架设计者的思维方式——当你下次面对"为什么 React 要这样做"的问题时,你能从第一性原理给出答案。

18.1 React 源码中的 10 个核心设计模式

React 的源码从来不是为了展示设计模式而写的——它是为了解决问题。但当你用设计模式的"棱镜"去观察这些解决方案时,会发现 Gang of Four 书中的经典模式几乎无处不在。以下是 React 源码中最核心的 10 个设计模式,按照它们在渲染流程中出现的顺序排列。

18.1.1 Observer 模式:状态变更的订阅与通知

Observer(观察者)模式是 React 响应式系统的基石。当你调用 setState 时,React 需要知道哪些组件依赖了这个状态,然后通知它们重新渲染。这本质上就是一个发布-订阅关系。

typescript
// React 中 Observer 模式的核心体现:useState 的更新链路
// 文件:packages/react-reconciler/src/ReactFiberHooks.js

function dispatchSetState<S, A>(
  fiber: Fiber,
  queue: UpdateQueue<S, A>,
  action: A
): void {
  // 1. 创建 update 对象("事件")
  const update: Update<S, A> = {
    lane,
    revertLane: NoLane,
    action,      // 用户传入的新值或 updater 函数
    hasEagerState: false,
    eagerState: null,
    next: null as any,
  };

  // 2. 将 update 入队("通知"排队)
  const alternate = fiber.alternate;
  if (fiber === currentlyRenderingFiber ||
      (alternate !== null && alternate === currentlyRenderingFiber)) {
    // 渲染阶段的更新,特殊处理
    didScheduleRenderPhaseUpdateDuringThisPass = true;
    // ...
  } else {
    // 3. 调度更新("通知"观察者)
    const root = enqueueConcurrentHookUpdate(fiber, queue, update, lane);
    if (root !== null) {
      scheduleUpdateOnFiber(root, fiber, lane);  // 触发重新渲染
    }
  }
}

这段代码是经典 Observer 模式的 React 变体。useState 返回的 setState 函数就是"发布"操作,而 scheduleUpdateOnFiber 则是通知调度器"有东西变了,需要重新渲染"。但与传统 Observer 不同的是,React 不直接通知每个组件,而是通知调度器——由调度器决定何时、以何种优先级去"通知"(重新渲染)组件。这是一种间接观察者模式,调度器充当了中介。

深度洞察:Vue 使用的是直接 Observer 模式——每个响应式属性都维护自己的依赖列表,变更时直接通知依赖的 effect。React 则选择了间接模式——任何状态变更都先进入调度器,由调度器统一协调。这两种选择没有绝对优劣,但它们深刻地影响了两个框架的性能特征:Vue 的更新粒度更细(组件级),React 的调度能力更强(可中断、可排优先级)。

18.1.2 Strategy 模式:可插拔的协调策略

Strategy(策略)模式允许算法在运行时被替换。React 的 Reconciler 就是一个巨大的策略容器——它不关心最终的渲染目标是 DOM、Native 组件还是字符串,只负责协调逻辑。

typescript
// React Reconciler 的策略注入接口
// 文件:packages/react-reconciler/src/ReactFiberReconciler.js

// HostConfig 就是策略接口——不同的宿主环境提供不同的实现
export type HostConfig = {
  // 创建实例的策略
  createInstance(
    type: string,
    props: Props,
    rootContainerInstance: Container,
    hostContext: HostContext,
    internalInstanceHandle: Object
  ): Instance;

  // 创建文本节点的策略
  createTextInstance(
    text: string,
    rootContainerInstance: Container,
    hostContext: HostContext,
    internalInstanceHandle: Object
  ): TextInstance;

  // 提交更新的策略
  commitUpdate(
    instance: Instance,
    type: string,
    oldProps: Props,
    newProps: Props,
    internalInstanceHandle: Object
  ): void;

  // 添加子节点的策略
  appendChild(parentInstance: Instance, child: Instance | TextInstance): void;

  // ... 还有数十个策略方法
};

React DOM 实现了一套 HostConfig,React Native 实现了另一套,React Three Fiber(3D 渲染)实现了又一套。Reconciler 的核心代码完全不需要改变——这就是 Strategy 模式的威力。

typescript
// react-dom 的策略实现
// 文件:packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

export function createInstance(
  type: string,
  props: Props,
  rootContainerInstance: Container,
  hostContext: HostContext,
  internalInstanceHandle: Object
): Instance {
  const domElement: Instance = createElement(type, props, rootContainerInstance, hostContext);
  precacheFiberNode(internalInstanceHandle, domElement);
  updateFiberProps(domElement, props);
  return domElement;
}

// react-native 的策略实现则完全不同——创建的是 Native View 而不是 DOM Element

18.1.3 Factory 模式:Fiber 节点的创建

Factory(工厂)模式在 React 中最显著的应用是 Fiber 节点的创建。React 需要根据不同的 Element 类型(函数组件、类组件、原生元素、Fragment、Portal 等)创建不同结构的 Fiber 节点。

typescript
// Fiber 创建的工厂逻辑
// 文件:packages/react-reconciler/src/ReactFiber.js

export function createFiberFromElement(
  element: ReactElement,
  mode: TypeOfMode,
  lanes: Lanes
): Fiber {
  const type = element.type;
  const key = element.key;
  const props = element.props;

  let fiberTag: WorkTag = IndeterminateComponent; // 默认为"待确定"类型

  if (typeof type === 'function') {
    // 函数组件或类组件(此时还不确定,需要后续在 beginWork 中判断)
    if (shouldConstruct(type)) {
      fiberTag = ClassComponent;
    } else {
      fiberTag = FunctionComponent;
    }
  } else if (typeof type === 'string') {
    // 原生 DOM 元素:div、span、p 等
    fiberTag = HostComponent;
  } else {
    // 特殊类型:Fragment、Suspense、Portal 等
    getTag: switch (type) {
      case REACT_FRAGMENT_TYPE:
        return createFiberFromFragment(props.children, mode, lanes, key);
      case REACT_SUSPENSE_TYPE:
        fiberTag = SuspenseComponent;
        break getTag;
      case REACT_SUSPENSE_LIST_TYPE:
        fiberTag = SuspenseListComponent;
        break getTag;
      // ... 更多类型
    }
  }

  const fiber = createFiber(fiberTag, props, key, mode);
  fiber.elementType = type;
  fiber.type = type;
  fiber.lanes = lanes;
  return fiber;
}

基于 VitePress 构建