5.4 案例分析与实战项目


文档摘要

5.4 案例分析与实战项目 订单管理中台是贯穿本节的实战项目:从一张需求清单出发,用 5.1 的三层骨架落地、5.2 的库边界拆分、5.3 的模式填肉,再用第 3 章的手段做性能收口,最后启用 SSR 与 PWA 上线。主线在每一站各现身一次——第一次点击时的 Zone 哨兵、列表滚动时的 OnPush 跳过、筛选联动时的信号调度、首屏直出时的服务端检查。读完本节,全册的知识在同一个项目里对上了号。 上一节留下的钩子 5.3 结尾说"模式是机制的执行手段",留下的钩子是:这些手段拼在一起,能不能撑起一个真实项目从零到上线的全程?本节用一个订单管理中台作答,动手中需要达成: 按需求清单完成架构决策记录,说出每层选型与主线的关系。 实现订单列表与详情两个页面,覆盖取数、缓存、鉴权、错误重试。

5.4 案例分析与实战项目

订单管理中台是贯穿本节的实战项目:从一张需求清单出发,用 5.1 的三层骨架落地、5.2 的库边界拆分、5.3 的模式填肉,再用第 3 章的手段做性能收口,最后启用 SSR 与 PWA 上线。主线在每一站各现身一次——第一次点击时的 Zone 哨兵、列表滚动时的 OnPush 跳过、筛选联动时的信号调度、首屏直出时的服务端检查。读完本节,全册的知识在同一个项目里对上了号。

上一节留下的钩子

5.3 结尾说"模式是机制的执行手段",留下的钩子是:这些手段拼在一起,能不能撑起一个真实项目从零到上线的全程?本节用一个订单管理中台作答,动手中需要达成:

  1. 按需求清单完成架构决策记录,说出每层选型与主线的关系。
  2. 实现订单列表与详情两个页面,覆盖取数、缓存、鉴权、错误重试。
  3. 用 profiler 实测优化前后数据,复现 OnPush 与 track 的收益。
  4. 完成构建与部署检查清单,说清 SSR 水合与 PWA 缓存各自的边界。

一、需求与架构决策

需求四条:订单列表(分页、按状态筛选、关键词搜索)、订单详情(含操作日志)、角色权限(客服只读、主管可改)、首屏一秒内可见。决策记录只有三行:

ADR-01 分层:data-sdk 仓储层 + order-domain 状态层 + 两个应用,依据 5.1 ADR-02 组件:页面级容器 + 哑组件全部 OnPush,列表用 track 复用行,依据 3.2 / 5.3 ADR-03 渲染:管理端不启用 SSR(内网系统),门户端启用 SSR + PWA,依据 3.7 / 3.8

架构决策记录的价值不是文档本身,而是把"为什么"钉在变更检测主线上:每个决策都对应一次可以复现的测量。列表页的 OnPush 改造有没有用,profiler 里看检查耗时;SSR 值不值得,首页直出时间说话。

二、列表页:主线第一次完整现身

// 容器:筛选条件变化 → 仓储取数 → 信号写入 → 检查恰好发生一次 @Component({ selector: 'app-order-list-page', imports: [OrderFilterComponent, OrderTableComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: ` <app-order-filter (filterChanged)="onFilter($event)"/> <app-order-table [rows]="rows()" [loading]="state().phase === 'loading'"/> ` }) export class OrderListPageComponent { private repo = inject(OrderRepository); private state = signal<PageState<Order[]>>({ phase: 'idle' }); rows = signal<Order[]>([]); onFilter(f: OrderFilter) { this.state.set({ phase: 'loading' }); // 状态机:进入加载态 this.repo.query(f).subscribe({ next: list => { // 数据到达:两条信号写入 this.rows.set(list); this.state.set({ phase: 'done', data: list }); }, error: () => this.state.set({ phase: 'error', retry: () => this.onFilter(f) }) }); } }
// 哑组件:行级 OnPush + track 复用,滚动翻页时旧行不重算 @Component({ selector: 'app-order-table', changeDetection: ChangeDetectionStrategy.OnPush, template: ` @for (r of rows(); track r.id) { <tr (dblclick)="open.emit(r.id)"> <td>{{ r.no }}</td><td>{{ r.customer }}</td> <td class="amt">{{ r.amount | number: '1.2-2' }}</td> <!-- 纯管道:引用不变就不重算 --> </tr> } ` }) export class OrderTableComponent { rows = input.required<Order[]>(); open = output<string>(); }

主线在此处完整现身:客服在筛选框敲回车,Zone 哨兵报告一次异步事件结束,Angular 从根往下检查;容器输入新引用触发表格重绘,纯管道按引用跳过、track 命中的行直接复用。一次用户操作对应一轮检查、一轮检查里只有真正变化的绑定被重算——这就是全册反复打磨的那句话的工程形态。

三、性能收口:改造前后各测一次

指标 改造前(默认策略) 改造后(OnPush + track + 信号)
翻页一轮检查耗时 8.4 ms 1.9 ms
检查的组件数 全页 47 个 9 个
筛选输入到出结果 120 ms 46 ms

改造清单全部来自 3.2 与 5.3:容器与哑组件分层、输入只传不可变值、行组件 track 订单编号、筛选防抖 300 毫秒后仍由信号调度。数字本身不惊人,惊人的是方法可复现——任何读者按同一清单改造自己的页面,应能得到同方向的结论。

图:订单中台上线全程与主线现身点

图:订单中台上线全程与主线现身点

四、部署与验收:最后两条主线延伸

门户端启用 SSR 后首次有意义绘制从 2.8 秒缩到 0.9 秒,代价是要处理服务端与浏览器差异(3.8 节的 window 报错清单照抄即用);PWA 的 Service Worker 缓存住静态资源,断网时最近一页订单仍可查看——两条延伸各守住一种"检查不发生"的场景:前者让首屏检查提前到服务端完成,后者让离线时连框架都不用启动。验收清单最后一项写给半年后的维护者:profiler 截图与 ADR 存档在同一目录,谁质疑性能,先跑一遍同样的测量

本节要点回顾

  • 决策可测量:ADR 只写与主线相关的取舍,每条决策配一份前后对照数据。
  • 页面即模板:容器取数、哑组件呈现、状态机管迁移,5.3 的模式原样落地。
  • 优化可复现:OnPush、track、防抖、信号四板斧带来一个数量级的检查范围收敛。
  • 延伸有边界:SSR 换首屏、PWA 换离线,各自解决一类"检查不发生"的场景。
  • 主线收口:一次操作一轮检查、一轮检查只重算变化——从第 1 章的实验到本节的生产系统,这条主线没有变过。

全册至此收口。回到自己的项目时,建议带着第 3 章的 profiler 截图习惯与本章的 ADR 模板:机制在书里,判断在你手上。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U