
关于
现代 Angular(v20+)专家,深入掌握 Signals、独立组件、无 Zone 应用、SSR 和 Angular 最新特性。
name: angular description: 现代 Angular (v20+) 专家,精通 Signals、独立组件、无 Zone 应用、SSR/水合以及响应式模式。 risk: safe source: self date_added: '2026-02-27'
Angular 专家
掌握现代 Angular 开发:Signals、独立组件、无 Zone 应用、SSR/水合以及最新的响应式模式。
何时使用此技能
- 构建新的 Angular 应用 (v20+)
- 实现基于 Signals 的响应式模式
- 创建独立组件并从 NgModules 迁移
- 配置无 Zone 的 Angular 应用
- 实现 SSR、预渲染和水合
- 优化 Angular 性能
- 采用现代 Angular 模式和最佳实践
不适用场景
- 从 AngularJS (1.x) 迁移 → 使用
angular-migration技能 - 处理无法升级的旧版 Angular 应用
- 通用 TypeScript 问题 → 使用
typescript-expert技能
操作步骤
- 评估 Angular 版本和项目结构
- 应用现代模式(Signals、独立组件、无 Zone)
- 使用正确的类型和响应式实现
- 通过构建和测试验证
安全注意事项
- 始终在开发环境中测试后再部署到生产环境
- 对现有应用采用渐进式迁移(避免一次性大规模重构)
- 在过渡期间保持向后兼容性
Angular 版本时间线
| 版本 | 发布时间 | 关键特性 | | -------------- | -------- | ------------------------------------------- | | Angular 20 | 2025 Q2 | Signals 稳定版、无 Zone 稳定版、增量水合 | | Angular 21 | 2025 Q4 | Signals 优先默认、增强 SSR | | Angular 22 | 2026 Q2 | Signal 表单、无选择器组件 |
1. Signals:新的响应式原语
Signals 是 Angular 的细粒度响应式系统,取代了基于 zone.js 的变更检测。
核心概念
import { signal, computed, effect } from "@angular/core";
// Writable signal
const count = signal(0);
// Read value
console.log(count()); // 0
// Update value
count.set(5); // Direct set
count.update((v) => v + 1); // Functional update
// Computed (derived) signal
const doubled = computed(() => count() * 2);
// Effect (side effects)
effect(() => {
console.log(`Count changed to: ${count()}`);
});
基于 Signal 的输入和输出
import { Component, input, output, model } from "@angular/core";
@Component({
selector: "app-user-card",
standalone: true,
template: `
<div class="card">
<h3>{{ name() }}</h3>
<span>{{ role() }}</span>
<button (click)="select.emit(id())">Select</button>
</div>
`,
})
export class UserCardComponent {
// Signal inputs (read-only)
id = input.required<string>();
name = input.required<string>();
role = input<string>("User"); // With default
// Output
select = output<string>();
// Two-way binding (model)
isSelected = model(false);
}
// Usage:
// <app-user-card [id]="'123'" [name]="'John'" [(isSelected)]="selected" />
Signal 查询 (ViewChild/ContentChild)
import {
Component,
viewChild,
viewChildren,
contentChild,
} from "@angular/core";
@Component({
selector: "app-container",
standalone: true,
template: `
<input #searchInput />
<app-item *ngFor="let item of items()" />
`,
})
export class ContainerComponent {
// Signal-based queries
searchInput = viewChild<ElementRef>("searchInput");
items = viewChildren(ItemComponent);
projectedContent = contentChild(HeaderDirective);
focusSearch() {
this.searchInput()?.nativeElement.focus();
}
}
Signals 与 RxJS 的使用场景对比
| 使用场景 | Signals | RxJS |
| ----------------- | --------------- | -------------------------------- |
| 本地组件状态 | ✅ 推荐 | 过于复杂 |
| 派生/计算值 | ✅ computed() | combineLatest 可用 |
| 副作用 | ✅ effect() | tap 操作符 |
| HTTP 请求 | ❌ | ✅ HttpClient 返回 Observable |
| 事件流 | ❌ | ✅ fromEvent、操作符 |
| 复杂异步流 | ❌ | ✅ switchMap、mergeMap |
2. 独立组件
独立组件是自包含的,不需要 NgModule 声明。
创建独立组件
import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink } from "@angular/router";
@Component({
selector: "app-header",
standalone: true,
imports: [CommonModule, RouterLink], // Direct imports
template: `
<header>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
</header>
`,
})
export class HeaderComponent {}