Angular v22 正式落地。这次更新最大的信号是:多个此前标记为"实验性"的特性正式摘帽,进入生产就绪状态。对日常写业务代码的开发者而言,最直接的冲击来自 Signal Forms——一套彻底重构的响应式表单 API,它把过去两套割裂的表单方案揉合成了声明式、可组合的新形态。同时,Angular Aria 让无障碍支持不再依赖手动堆属性,而面向 AI Agent 的开发工具链也补齐了最后一块拼图。
告别割裂:Signal Forms 终结"两套表单"时代
过去在 Angular 里写表单,开发者始终面临一个选择题:用 Reactive Forms 还是 Template-driven Forms?
Reactive Forms 提供了强大的动态组合能力和同步校验模型,但代价是大量的 RxJS map、filter 和 subscribe 样板代码;Template-driven Forms 写法轻量,直接在模板上绑指令,但遇到复杂嵌套或异步交叉校验时往往力不从心。两套体系的 API 互不相通,状态追踪路径也完全不同。
Signal Forms 的出现直接终结了这种割裂。它基于 Angular Signals 构建,把响应式表单的可组合性与模板驱动表单的声明式体验融合到了一套 API 里。底层状态变更通过 Signal 传播,不再依赖 Observable 流;上层消费直接用 computed 派生校验状态,像操作普通变量一样处理表单,彻底砍掉了 RxJS 的订阅心智负担。
Angular Aria:无障碍不再是体力活
无障碍(Accessibility)一直是前端工程里"重要性极高、实操优先级极低"的典型区域。写一个复杂的自定义下拉组件,开发者往往需要手动堆砌 role="combobox"、aria-expanded、aria-activedescendant 等大量属性,还要精确管理焦点跳转。
Angular Aria 在 v22 进入生产就绪,它把这些语义属性和焦点管理内化到了框架层。通过指令的自动绑定与状态推断,组件开发者只需关注业务逻辑与视觉结构,ARIA 属性由框架根据交互状态自动注入。这对维护大型组件库的团队来说,直接砍掉了一半以上的无障碍回归测试成本。
AI Agent 开发基础设施补齐
v22 另一条隐秘但关键的线索是对 AI Agent 开发的全面支持。当前大模型与前端框架的交互大多停留在"生成代码片段"的层面,但要让 AI Agent 真正自主操作页面、理解组件结构并执行多步任务,框架必须暴露出结构化的组件元数据与可编程的交互接口。
Angular 在 v22 中将此前实验性的 AI 开发工具推向生产化,提供了更完整的组件树解析、状态快照与操作回放基础设施。这意味着基于 Angular 构建的应用,可以更容易地被外部 Agent 理解和驱动,而不是仅仅被当作一团无结构的 DOM。
上手实践:用 Signal Forms 写一个登录表单
下面是一个基于 v22 Signal Forms API 构建的登录组件示例。它展示了如何用声明式的方式组合表单,并用 computed 直接派生校验状态,无需任何 RxJS 管道。
注意:以下代码基于摘要描述与 Angular Signals RFC 推断的 API 形态编写。包导入路径与具体校验配置项在最终正式版中可能存在微调,运行前请确认当前安装的 @angular/forms 版本对 Signal Forms 的具体导出名称。
// login.component.ts
import { Component, computed } from '@angular/core';
import { formGroup, formControl } from '@angular/forms/signals';
@Component({
selector: 'app-login',
standalone: true,
template: `
<form [formGroup]="loginForm">
<label>
用户名
<input type="text" formControlName="username" placeholder="请输入用户名">
</label>
<label>
密码
<input type="password" formControlName="password" placeholder="请输入密码">
</label>
<!-- 直接消费 computed signal,无需异步订阅 -->
<button type="submit" [disabled]="!canSubmit()">登录</button>
@if (loginForm.controls.password.errors()?.minLength) {
<small style="color: red;">密码长度不能少于 6 位</small>
}
</form>
`
})
export class LoginComponent {
// 声明式组合表单模型,底层完全由 Signal 驱动
loginForm = formGroup({
username: formControl('', { required: true }),
password: formControl('', { required: true, minLength: 6 }),
});
// 像操作普通变量一样派生表单状态
canSubmit = computed(() => this.loginForm.valid());
onSubmit() {
if (this.canSubmit()) {
const rawValue = this.loginForm.value();
console.log('提交数据:', rawValue);
// 发起实际登录请求...
}
}
}
改造提示:如果你要在现有项目中试验,可以先在一个新建的独立组件中引入 Signal Forms,与现有的 Reactive Forms 组件并行运行,观察两者在状态更新延迟与代码量上的差异。
升级与落地建议
v22 的这几个特性虽然摘掉了实验标签,但落地时仍有明确的边界需要考量:
- 渐进式迁移表单:现有的 Reactive Forms 代码无需立刻重写。v22 保留了旧 API 的完整兼容,Signal Forms 可以仅用于新模块或新组件,两种表单体系在同一应用内可以共存。建议先在表单逻辑较简单的场景(如登录、搜索框)中验证 Signal Forms 的开发体验,再逐步向复杂动态表单渗透。
- 无障碍改造的时机:Angular Aria 的自动推断主要针对原生元素与标准交互模式。如果你的组件库重度依赖自定义交互(如非标准的拖拽排序、虚拟滚动列表),Aria 的自动注入可能无法完全覆盖,仍需手动补齐特定 ARIA 属性。
- 升级命令:直接通过 Angular CLI 完成核心升级:
bash ng update @angular/core @angular/cli升级后,检查tsconfig中的strictSignals配置(如果此前未开启,建议在迁移表单前先行开启,以获得完整的 Signal 类型检查保障)。
Signal Forms 不是对旧 API 的简单包装,而是基于 Signals 底层原语的重新定义。它意味着 Angular 的响应式模型正在从"流(Observable)为主"转向"信号(Signal)为主"。对于开发者来说,现在正是上手理解 Signal 思维、并在新代码中实践的最佳窗口。