Solid 与细粒度更新

共 17 题
📑 题目列表 17 题
#
★★★

1. Solid 的细粒度响应式原理(信号+派生+effect),与 React 重新渲染的差异?

Solid 的细粒度响应式原理(信号、派生、effect)是什么?与 React 的重新渲染模型有何差异?

  • createSignal/createMemo/createEffect 的依赖追踪机制
  • JSX 编译为表达式级 effect 的细粒度更新
  • 与 React 组件重渲染模型的核心差异

Solid 以信号为响应式基石:createSignal 创建"读-写"对,读取时在当前执行上下文(观察者)中注册依赖,写入时通知所有依赖该信号的观察者;createMemo 派生并缓存计算值,仅在依赖变化时重算;createEffect 执行副作用并自动追踪其读取的信号。JSX 在编译期被分解为表达式级 effect——每个模板插值都是一个独立更新单元,组件函数只在首次创建时执行一次,此后信号变化直接更新对应 DOM 表达式,更新粒度精确到表达式。

与 React 的差异是范式级的:React 中状态变化导致组件函数重新执行、生成新虚拟 DOM 树并 diff;Solid 没有虚拟 DOM、没有"重新渲染组件"的概念,组件是"构建响应式订阅图"的一次性函数,更新成本与组件大小无关、与表达式数量相关。React 需要 memo/useMemo 手工优化避免多余重渲染,Solid 的细粒度追踪天然避免无关更新,但要求开发者把"每次渲染要重算的逻辑"放进 memo/effect 而非组件体内。

本题考察 Solid 响应式模型的核心。回答要点是"读收集、写通知"的追踪机制与 JSX 编译为表达式 effect 的产物,再与 React 重渲染对比,突出"无重渲染"与"表达式级更新"两个关键差异。

const [count, setCount] = createSignal(0);
const doubled = createMemo(() => count() * 2);
createEffect(() => console.log(count(), doubled()));
// 模板中 {doubled()} 只更新该表达式节点
#
★★★

2. Solid 的依赖追踪,createMemo 如何缓存派生值,effect 的订阅与清理时机如何管理?

Solid 的依赖追踪中,createMemo 如何缓存派生值?createEffect 的订阅与清理时机如何管理?

  • memo 的惰性求值与依赖脏标记
  • effect 的自动依赖收集与重跑时机
  • onCleanup 的清理注册与执行时机

createMemo 创建的派生信号在首次读取时计算并缓存结果,此后只有其依赖信号被写入时才被标记为脏,再次读取时重算,未变时直接返回缓存,从而避免重复计算;memo 可以嵌套使用并被其他 memo/effect 依赖,形成响应式派生图。createEffect 在创建时同步执行一次以收集依赖,之后任一依赖信号变化时在更新阶段重新执行,执行前先运行上一次注册的清理函数。

清理管理:effect 内部调用 onCleanup 注册清理回调,在"重跑前"与"组件卸载时"执行,用于取消订阅、清除定时器、销毁对象等。常见陷阱:在 effect 中写入其自身依赖的信号会造成循环触发,应拆分逻辑或用条件写入;effect 不应在更新阶段读取未完成计算的派生值(信号更新异常),批量状态变更用 batch 合并通知。理解"创建时收集、变化时重跑、重跑前清理"是掌握 Solid 依赖追踪的关键。

本题考察 Solid 依赖追踪的完整时序。回答要点:memo 的惰性缓存与脏标记、effect 的收集/重跑/清理三阶段、循环写入与批量更新的注意点。

#
★★★

3. Solid Store(createStore)的代理与不可变更新,为什么 Store 的字段级订阅比信号更节省内存,在大型表单/树状数据中如何取舍?

Solid Store(createStore)的代理与不可变更新机制是怎样的?为什么字段级订阅比信号更节省内存?在大型表单/树状数据中如何取舍?

  • createStore 的 Proxy 包装与路径化更新(setState)
  • 渐进式代理的字段级订阅与内存优势
  • 大型表单/树状数据的取舍与使用模式

createStore 用 Proxy 包装对象并支持路径化更新:setState('user', 'name', value) 或 setState(prev => ({...})) 局部更新指定路径,保持不可变更新语义的同时避免整体替换;读取 store 的表达式(store.user.name)被追踪到字段粒度。关键设计是"渐进式代理":Store 只在访问的路径上按需创建代理与订阅节点,未被读取的分支不产生追踪开销,因此大型嵌套数据结构中字段级订阅的依赖数量远少于"每字段一个信号"的方案,内存与通知开销更低。

取舍:大型表单、树状数据、配置对象用 Store——字段级更新精准、依赖数量可控;独立、更新频繁、结构简单的小状态用 createSignal——更轻量直接。实践模式:setState 用路径或函数式更新避免整对象替换;深层路径频繁变化时注意闭包中旧引用的过期问题(用函数式更新读取最新值);Store 与信号可以混用(Store 字段派生用 createMemo 缓存)。

本题考察 Solid Store 的设计精髓。回答要点:路径化不可变更新、渐进式代理带来的字段级订阅与内存优势、按数据形态选择 Store 或信号的取舍原则。

#
★★

4. Solid 与 Signals 生态对比,Preact Signals、Million 等框架/库与 Solid 的细粒度实现与生态成熟度差异?

Solid 与 Preact Signals、Million 等 Signals 生态框架/库相比,细粒度实现与生态成熟度有何差异?

  • 各家信号的实现路线(编译期 vs 运行时集成)
  • 更新粒度与虚拟 DOM 的取舍
  • 生态成熟度与适用场景

各家共享"信号 + 依赖追踪"的响应式思想,但工程路线不同:Solid 把 JSX 编译为细粒度表达式 effect,无虚拟 DOM,更新粒度最细;Preact Signals 在 Preact 兼容层做运行时集成,保留虚拟 DOM 但用信号绕过组件重渲染(只重渲染订阅信号的组件),兼容 React 生态是其主要卖点;Million 是编译器优化的"block 虚拟 DOM",信号驱动的块级更新,聚焦列表与高更新场景的性能补丁。实现上,编译期方案(Solid/Million)在构建期确定依赖,运行时方案(Preact Signals)更灵活但需代理与订阅层。

生态成熟度:Solid 拥有完整框架能力(路由、SSR、SolidStart、组件库如 Kobalte),但组件库与工具链规模仍小于 React/Vue 生态;Preact Signals 借助 Preact 的 React 兼容性继承大量生态,迁移成本低;Million 定位为性能优化库而非独立框架,生态最薄。选型:追求极致细粒度与独立技术栈选 Solid;需要 React 生态兼容且想引入信号选 Preact Signals;只想给现有应用局部提速可评估 Million。

本题考察 Signals 生态的横向对比。回答按"实现路线—更新粒度—生态成熟度"三层展开,明确各自的定位与适用场景,避免笼统比较。

#
★★

5. Solid 的 Store 与 Signals,细粒度订阅的取舍?

Solid 中 Store 与 Signals(信号)在细粒度订阅上如何取舍?

  • 信号适合独立状态单元、Store 适合结构化数据
  • 订阅粒度与依赖数量的权衡
  • 更新模式(整体替换 vs 局部更新)的匹配

信号(createSignal)的粒度是"信号本身":适合独立、更新频繁的单一状态(计数器、开关、当前选中项),读写在组件间显式传递;Store(createStore)的粒度可到"字段路径":适合嵌套结构(表单、树、配置),一个 Store 可以承载大量字段而依赖数量仍受控,字段级订阅避免了"一个字段一个信号"的依赖爆炸。

取舍依据:数据形态——扁平独立状态用信号,嵌套结构化数据用 Store;更新模式——频繁整体替换(如轮询返回的新对象)用信号 + 整体赋值,局部小步更新(表单输入)用 Store 路径更新;性能——字段级追踪依赖更少、通知更精准,但 Store 路径写法更繁琐、可读性成本高。实践中两者混用是常态:Store 承载结构化数据、信号承载独立状态、createMemo 承接派生计算,按"变化的最小单位"选择承载原语。

本题考察响应式原语的选择方法。回答要点是"粒度匹配":独立状态→信号、结构化局部更新→Store、按变化最小单位选择,并说明混用模式。

#
★★

6. Solid 的 createResource 与 Suspense,异步资源加载、refetching 与错误处理在数据获取层的工程价值?

Solid 的 createResource 与 Suspense 如何实现异步资源加载?refetching 与错误处理在数据获取层有何工程价值?

  • createResource(source, fetcher) 的响应式请求模型
  • Suspense 占位与嵌套加载
  • refetch/mutate 与 error 状态的处理

createResource 接收响应式 source 与 fetcher 函数,返回资源对象:source 变化时自动重新请求,结果暴露为 {data, loading, error} 的响应式访问器;Suspense 组件捕获尚未完成的资源,在 fallback 中渲染占位内容,支持嵌套 Suspense 与并行资源加载(等待所有子树资源完成),配合 useTransition/startTransition 控制导航与加载体验。请求生命周期(loading/error/data)被声明式收敛,避免手写状态机。

工程价值:refetch 提供手动刷新入口、mutate 支持本地乐观更新缓存,组合成"请求-缓存-刷新"的数据获取层;error 状态可单独渲染错误视图或配合 ErrorBoundary 降级;SSR 场景资源在服务端解析后与客户端水合衔接,配合缓存策略避免重复请求。注意:fetcher 中不要读取响应式值以外的副作用依赖、资源清理(onCleanup 取消请求)与竞态(source 快速变化时只保留最新请求)是常见坑。

本题考察 Solid 数据获取层的声明式模型。回答要点:createResource 的 source/fetcher 模型、Suspense 的占位与嵌套、refetch/mutate/error 组成的完整工程闭环。

#
★★

7. Solid 中 createSignal/createMemo/createEffect 的依赖追踪机制?

Solid 中 createSignal、createMemo、createEffect 的依赖追踪机制是如何运作的?

  • 全局追踪栈与观察者上下文
  • 读取收集依赖、写入通知订阅
  • memo/effect 的嵌套与更新顺序

Solid 的依赖追踪基于"观察者上下文":createEffect/createMemo 执行时把自己设为当前观察者并压入全局追踪栈,执行体内读取信号 getter 即把"信号→观察者"的依赖关系登记到信号的订阅表;信号写入时遍历订阅表把依赖的观察者标记为脏并排队。createSignal 只提供读写原语;createMemo 是带缓存的派生观察者(自身也可被依赖);createEffect 是副作用观察者。嵌套追踪:在 effect 内创建的 memo/effect 形成父子关系,父清理时子一并清理。

更新阶段按依赖图的拓扑顺序批量执行:先更新 memo 再执行依赖它的 effect,同一批次内的多次写入只触发一次通知(隐式 batch),保证观察者看到一致的状态快照;观察者重跑前先运行 onCleanup 清理。理解"读收集、写通知、拓扑批量更新"即可掌握 Solid 响应式的全部机制,这也是其无虚拟 DOM、无 diff 的性能根基。

本题考察依赖追踪的实现细节。回答要点是观察者上下文与全局追踪栈、依赖的双向登记、memo/effect 的嵌套与拓扑更新顺序。

#
★★

8. Solid 的 Show/For/Index 控制流组件为何比 map 更高效?

Solid 的 Show/For/Index 控制流组件为什么比直接在 JSX 中 map 更高效?

  • map 重建 JSX 表达式与依赖断裂的问题
  • Show/For/Index 的持久化模板与 keyed 复用
  • 控制流组件的编译期优化

在 JSX 中直接 map 返回数组渲染列表时,每次组件函数(或外层响应式区域)重执行都会整体重建列表 DOM,且闭包内读取的信号依赖在重建后需要重新建立,容易导致依赖丢失或重复追踪;更重要的是 map 本身不具备"增删移动"的差异化能力。Show 把条件分支编译为持久化模板:条件变化时只切换分支,模板表达式与依赖保持稳定;For 按 keyed 语义(项标识)复用 DOM 与组件实例,数据变化只更新受影响项,配合 fallback 处理空列表;Index 以索引为 key,适合值不变的纯展示列表。

控制流组件之所以高效,是因为它们在编译期被识别为响应式容器:模板只创建一次、数据驱动更新,表达式依赖在初始创建时收集完毕,后续更新直接命中对应节点,避免 map 的全量重建与依赖断裂。选择上:条件用 Show、需要 keyed 的列表用 For、以索引为准的固定值列表用 Index。

本题考察控制流组件与 map 的本质差异。回答要点:map 是"重建"而 Show/For/Index 是"更新"、模板持久化与 keyed 复用、依赖收集只发生一次。

#
★★

9. Show/For/Index 控制流组件相比 JSX map 的优势与 keyed 语义差异?

Show/For/Index 控制流组件相比 JSX map 有哪些优势?For 与 Index 的 keyed 语义有何差异?

  • 条件/列表的响应式模板与 fallback 支持
  • For 的 keyed(按值复用)与 Index 的按索引复用
  • 选型:何时用 For、何时用 Index

相比 map,控制流组件把模板编译为持久化的响应式片段:Show 的条件分支、For/Index 的列表项只在创建时建立依赖,更新直接命中差异节点;它们都支持 fallback(Show 的 else、For/Index 的空态)与嵌套组合,配合 transition group 类库还能做进出场动画。keyed 语义是核心差异:For 默认以数据项标识(keyed: true)复用 DOM 与组件实例——数据移动、增删时组件状态与 DOM 节点跟随"数据身份"迁移,保证正确性;Index 以数组索引为 key——适合项不可变、无状态的纯展示列表,避免 keyed 计算开销,但插入/删除会导致后续项实例错位,依赖自身状态或顺序渲染的组件会串位。

选型规则:列表项含组件内部状态、可能增删移动、顺序可变时用 For(keyed);列表项是纯值展示、以位置为准、不会插入删除时用 Index 或直接 map;条件渲染用 Show。理解 keyed 语义即理解"哪个实例对应哪条数据",是控制流组件正确使用的关键。

本题考察控制流组件的优势与 keyed 语义细节。回答要点:持久化模板与 fallback 优势、For 按值 vs Index 按索引的差异、按数据形态选择组件的规则。

#
★★

10. SolidStart 的 server functions 与路由数据加载如何实现"零序列化开销"的服务端集成?

SolidStart 的 server functions 与路由数据加载如何实现"零序列化开销"的服务端集成?

  • createServerFn 的编译期 RPC 机制
  • 路由数据加载(createAsync/query)与流式传输
  • 服务端执行、数据直达客户端的集成方式

SolidStart 用 createServerFn 定义服务端函数:编译器把它转换为客户端可调用的 RPC 桩(生成 fetch 请求与序列化协议),浏览器调用时自动发起到对应服务端端点执行,函数内可以安全访问数据库、密钥等服务端资源;调用结果按结构化协议返回。路由数据加载与 server functions 结合:在路由中声明 createAsync(或 createQuery)获取服务端数据,SolidStart 在服务端解析数据并通过流式传输(Suspense 边界)直达客户端,客户端不再重复请求,实现"一次获取、流式到达"。

"零序列化开销"的含义是:数据在服务端产出后直接流入客户端渲染管线,无需开发者手写 API 层、手动拼接请求与序列化业务对象;配合缓存(SWR/query 缓存)与错误流(服务器函数可抛错传递状态码),把数据获取、变更、缓存收敛为框架内建能力。注意点:server functions 只能被客户端调用或服务端调用、参数必须可序列化、权限校验应在服务端函数内完成。

本题考察 SolidStart 的全栈数据流设计。回答要点:createServerFn 的编译期 RPC、路由层数据加载与流式传输、数据直达客户端免去手工 API 层,并点出序列化与安全边界。

#
★★

11. batch/untrack/on 三个响应式工具函数的适用场景,什么时候需要手动合并更新、跳过依赖追踪或指定依赖?

Solid 的 batch、untrack、on 三个响应式工具函数分别适用什么场景?

  • batch 合并多次写入为一次通知
  • untrack 读取但不收集依赖
  • on 显式声明依赖并支持旧值访问

batch 把一批信号写入合并为一次通知:批量更新表单多个字段、初始化多个状态时,订阅者只收到一次更新,避免中间状态被观察到(也避免重复渲染);batch 可以嵌套,内部嵌套自动归并到外层批次。untrack 在读取信号时跳过依赖收集:effect 中只想读取"参考值"而不希望其变化触发重跑、或读取不相关状态时使用,防止过度订阅。on 显式指定依赖列表:on([a, b], fn, {defer}) 只在指定依赖变化时执行 fn,并可在回调内访问依赖旧值,适合"条件触发 + 需要前后对比"的场景(如路由参数变化、字段变更记录)。

三者的共同点是"手动接管自动追踪":默认的自动追踪覆盖大多数场景,batch/untrack/on 用于精确控制更新批次、依赖范围与触发条件。实践:表单批量提交用 batch、监听器内读取无关状态用 untrack、需要旧值或按需触发的副作用用 on。

本题考察 Solid 响应式工具函数的精确定位。回答要点是每个工具"控制什么"(通知批次/依赖收集/触发条件),并给出典型场景,体现对自动追踪语义的深入理解。

#
★★

12. Solid Context(createContext + Provider)与 React Context 的差异,为什么 Solid 中 Context 更新不会触发子树整体重渲染?

Solid 的 Context(createContext + Provider)与 React Context 有何差异?为什么 Solid 中 Context 更新不会触发子树整体重渲染?

  • createContext/Provider 的共享值机制
  • Solid 中 context 值读取即订阅的细粒度语义
  • React 消费组件整体重渲染 vs Solid 表达式级更新

两者都用于跨层级共享值:createContext 创建上下文、Provider 提供值、后代组件消费。差异在更新语义:React 中 context 值变化时,所有通过 useContext 消费该上下文的组件函数都会重新执行(重新渲染),即使只读取了部分字段;Solid 中 context 值通常是包含信号/Store 的对象,消费方在渲染中读取哪个字段就订阅哪个依赖,Provider 中信号变化只更新"读取了该信号的表达式",组件函数不重新执行,子树的其他部分不受影响。

根本原因:React 的更新单位是"组件函数"(重渲染+diff),Solid 的更新单位是"表达式"(订阅图节点)。因此 Solid 中 Context 更新不会触发子树整体重渲染——这是细粒度响应式模型的自然结果;也意味着 context 中只应传递"响应式值本身"(信号/Store)而非每次新建的普通对象,否则引用变化也可能导致多余更新。这一差异让 Solid 在多层级共享状态场景无需额外优化也能保持精确更新。

本题考察 Context 机制在两种响应式模型下的行为差异。回答要点:React 以组件为更新单位 vs Solid 以表达式为更新单位、context 中传递响应式值、根因是更新粒度的不同。

#

13. SolidStart 与 Solid 生态的现状与适用场景?

SolidStart 与 Solid 生态的现状如何?适用于什么场景?

  • SolidStart 的能力(SSR/岛屿/server functions/actions)
  • 生态规模与工具链现状
  • 适用场景与选型注意事项

SolidStart 是 Solid 的全栈框架:文件系统路由、SSR/SSG/岛屿渲染、server functions、表单 actions、WebSocket 与中间件支持,定位类似 Next.js,但以细粒度响应式为核心,客户端更新精确、服务端与客户端共享同一数据流。生态现状:核心框架与路由/SSR 已稳定,组件库(Kobalte、Solid UI)、表单与工具库持续完善,SSR 部署支持多种平台;但相比 React/Vue,组件库数量、第三方集成、招聘市场与文档社区规模仍有差距,企业级方案需要更多自建。

适用场景:性能敏感的应用(大列表、高频交互、资源受限设备)、创新项目与技术选型自由度高的团队、希望以"无虚拟 DOM + 细粒度更新"为核心卖点的产品;对生态丰富度、组件库成熟度与人才储备依赖强的项目需谨慎评估。SolidStart 特别适合"全栈 + 细粒度"的统一技术栈场景,采用前应验证关键第三方库的兼容性。

本题考察 Solid 生态的客观评估。回答要点:SolidStart 能力清单、生态的强项(响应式、全栈内聚)与短板(生态规模、人才),给出场景化结论。

#

14. Solid 细粒度更新在大型表单/列表场景的实战收益与调试成本?

Solid 细粒度更新在大型表单与列表场景有哪些实战收益?调试成本如何?

  • 大表单字段级更新与长列表差异更新的收益
  • 无需 memo 等手动优化的特点
  • 依赖追踪的调试视角与 DevTools 支持

实战收益:大型表单中每次输入只更新该字段绑定的表达式,不触发整表组件重跑与校验重算;万级行列表的增删改只更新对应行/单元格的 DOM,无 diff 开销;由于没有重渲染概念,无需 React 式的手动 memo/useCallback/useMemo 优化,代码更简洁且性能可预期。表单状态用 Store 字段级订阅、列表用 For keyed 复用,配合 createMemo 缓存派生计算,收益在数据规模大、更新频繁时非常显著。

调试成本:依赖追踪是运行时隐式行为,"为什么这个表达式没更新"需要检查订阅关系——Solid DevTools 提供组件数据与依赖图检查,但成熟度不如 React/Vue 的 DevTools;生成代码与 JSX 的映射依赖 sourcemap,部分场景栈定位不直观;从"重渲染心智"切换为"订阅心智"需要学习曲线,误用(在组件体内放每次更新都应执行的重逻辑、在 effect 中写循环依赖)会带来隐性 bug。总体:收益集中在性能敏感场景,成本主要是调试工具链与团队心智迁移。

本题考察细粒度更新的收益与代价平衡。回答要点:表单/列表场景的具体收益与"免手动优化"特性,同时客观指出调试工具成熟度与心智迁移成本。

#

15. SolidStart 的 Islands 与 Astro 的差异,客户端水合粒度与"零 JS 默认"策略的实现区别?

SolidStart 的 Islands 与 Astro 的差异是什么?客户端水合粒度与"零 JS 默认"策略的实现有何区别?

  • Astro 默认零 JS 与岛屿显式水合
  • SolidStart 全栈 SSR 与细粒度水合的形态
  • 两种策略的适用场景与实现差异

Astro 的默认策略是"零 JS":页面在构建/SSR 时输出纯静态 HTML,只有显式标注的岛屿(client:load、client:visible 等指令)才加载对应框架运行时并水合,天然支持多框架混用(React/Vue/Svelte 岛屿共存),定位是内容站与多框架整合。SolidStart 是完整的应用框架:默认全栈 SSR,可配置 islands 模式仅水合交互组件,但路由、数据加载、server functions、actions 深度集成,客户端逻辑与数据流是框架的一部分,单一 Solid 技术栈。

实现差异:Astro 的岛屿是"框架无关的独立水合单元",每个岛屿独立 chunk、独立根节点,靠指令声明时机;SolidStart 的岛屿基于 Solid 的细粒度运行时,水合粒度可以做到组件/表达式级,服务端与客户端共享同一响应式数据流。选型:内容驱动、多框架整合、SEO 优先选 Astro;全栈应用、单一技术栈、追求数据流统一与细粒度更新选 SolidStart。

本题考察两种岛屿化策略的定位差异。回答要点:"零 JS 默认"的声明方式、水合粒度、框架集成深度三个维度的对比,并落到场景化选型。

#

16. Solid 与 React 的渲染模型对比,组件只执行一次?

Solid 与 React 的渲染模型有何对比?为什么说 Solid 组件只执行一次?

  • Solid 组件作为"构建响应式订阅图"的一次性函数
  • React 组件作为随状态重执行的渲染函数
  • 对代码组织与性能的影响

React 的渲染模型是"函数重执行":状态变化时组件函数重新执行、生成新虚拟 DOM 并 diff,组件体内的计算、闭包与副作用逻辑每次渲染都会重跑,因此需要 memo/useCallback 等控制重执行范围。Solid 的渲染模型是"一次构建、订阅更新":组件函数只在首次创建时执行一次,执行过程中 JSX 表达式被编译为 effect 并建立信号依赖,此后信号变化直接更新对应 DOM 表达式,组件函数不再执行——所以"组件只执行一次"。

影响:Solid 组件体内放"每次渲染都执行"的逻辑(如事件绑定、计算渲染无关值)不会随数据变化重跑,需要主动用 createMemo 缓存派生值、createEffect 执行副作用;反过来,Solid 天然避免了无关状态变化引发的重渲染与闭包过期问题(不需要 useCallback 依赖数组)。对心智的要求:把"渲染期逻辑"与"副作用逻辑"明确分离,理解"响应式关系在创建时固定"。这也是 Solid 更新性能可预期的根本原因。

本题考察渲染模型的范式差异。回答要点:React 重执行 vs Solid 一次构建,以及由此带来的代码组织差异(memo 需求消失、副作用进 effect),点出"执行一次"的机制原因。

#

17. Solid 的 ErrorBoundary,错误边界、fallback 与错误重抛机制的设计?

Solid 的 ErrorBoundary 如何设计错误边界、fallback 与错误重抛机制?

  • ErrorBoundary 捕获子树渲染与生命周期错误
  • fallback 渲染与重置/重试机制
  • 错误重抛与嵌套边界的设计

Solid 的 ErrorBoundary 组件用捕获机制包裹子树:渲染期与 effect 中抛出的错误被边界捕获后,渲染 fallback 内容替代损坏的子树,避免整个应用崩溃;fallback 可以是静态内容或响应式视图(读取 error 状态展示错误信息)。重试与重置:边界内部持有错误信号,通过外部事件或信号重置后重新渲染子树,实现"从错误中恢复";错误也可以由边界再次抛出(throw)交给上层边界处理,形成嵌套错误链,每个边界按自己的策略降级或上报。

设计要点:边界按业务模块/路由划分而非全局一个,避免局部错误导致整页降级;fallback 提供明确的恢复入口(重试按钮)与错误上下文;日志上报(对接监控)与 UI 降级分离——边界负责 UI,上报走独立工具;异步资源(createResource)的 error 状态通常单独处理,不依赖渲染边界。ErrorBoundary 只能捕获渲染/生命周期错误,事件处理器中的错误需自行 try/catch 或走全局处理。

本题考察错误边界的工程化设计。回答要点:捕获范围、fallback 与重置机制、嵌套重抛链,以及"上报与降级分离"的设计原则与边界限制。