Appearance
第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 Element18.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;
}