本文件使用 Web 特定模式扩展 common/patterns.md。
Web 模式¶
组件组合¶
复合组件¶
当相关 UI 共享状态和交互语义时,使用复合组件:
<Tabs defaultValue="overview">
<Tabs.List>
<Tabs.Trigger value="overview">Overview</Tabs.Trigger>
<Tabs.Trigger value="settings">Settings</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="overview">...</Tabs.Content>
<Tabs.Content value="settings">...</Tabs.Content>
</Tabs>
- 父组件拥有状态
- 子组件通过上下文消费
- 对于复杂组件,优先使用这种方式而不是 props 透传
渲染属性 / 插槽¶
- 当行为共享但需要改变标记时,使用渲染属性或插槽模式
- 键盘处理、ARIA、焦点逻辑保留在 headless 层
容器 / 展示分离¶
- 容器组件拥有数据加载和副作用
- 展示组件接收 props 并渲染 UI
- 展示组件应保持纯粹
状态管理¶
将这些分别处理:
| 关注点 | 工具 |
|---|---|
| 服务器状态 | TanStack Query、SWR、tRPC |
| 客户端状态 | Zustand、Jotai、signals |
| URL 状态 | search params、route segments |
| 表单状态 | React Hook Form 或等效方案 |
- 不要将服务器状态复制到客户端存储
- 不要保存冗余的派生状态,而是导出值
作为状态的 URL¶
将可共享的状态持久化到 URL: - 筛选 - 排序顺序 - 分页 - 活动标签页 - 搜索查询
数据获取¶
Stale-While-Revalidate¶
- 立即返回缓存数据
- 在后台重新验证
- 优先使用现有库而不是手动实现
乐观更新¶
- 获取当前状态的快照
- 应用乐观更新
- 失败时回滚
- 回滚时提供可见的错误反馈
并行加载¶
- 并行获取独立数据
- 避免父子请求瀑布
- 在有正当理由时,预取下一个路由或状态
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC