入门教程 - 企业级框架核心概念

知识库
知识库文档
/tech-stacks/angular/tutorial/入门教程 - 企业级框架核心概念.md

文档

Angular 入门教程:企业级框架核心概念

一、Angular 是什么?

Angular 是由 Google 维护的企业级前端框架(2016 年发布 Angular 2,与 2010 年的 AngularJS 完全不同)。它是一个完整的解决方案——包含路由、表单、HTTP 客户端、状态管理、测试工具、SSR,开箱即用。使用 TypeScript 开发,强制采用 RxJS 进行异步编程。

核心哲学

"电池全包含"——不让你纠结选什么路由库、状态管理,Angular 都提供了官方方案。

二、核心概念地图

NgModule(模块)
  ├── Component(组件)—— 视图 + 逻辑
  │     ├── Template(HTML 模板)
  │     └── Class(TypeScript 类)
  ├── Service(服务)—— 业务逻辑,可注入
  │     └── @Injectable()
  ├── Pipe(管道)—— 数据转换
  └── Directive(指令)—— 行为增强

Standalone Components(Angular 15+)

@Component({
  standalone: true,           // 不再需要 NgModule
  imports: [CommonModule],    // 直接导入依赖
  template: `<h1>{{ title }}</h1>`,
})
export class MyComponent {
  title = "Hello";
}

三、数据绑定四种方式

<!-- 1. 插值:组件 → 模板 -->
<h1>{{ title }}</h1>

<!-- 2. 属性绑定:组件 → 模板(用方括号) -->
<img [src]="imageUrl" />

<!-- 3. 事件绑定:模板 → 组件(用圆括号) -->
<button (click)="onSave()">保存</button>

<!-- 4. 双向绑定:双向同步(香蕉盒 [()]) -->
<input [(ngModel)]="username" />

四、控制流(Angular 17+ 新语法)

<!-- @if / @else -->
@if (user(); as user) {
  <p>欢迎, {{ user.name }}</p>
} @else {
  <p>请登录</p>
}

<!-- @for(替代 *ngFor) -->
@for (item of items; track item.id; let i = $index) {
  <li>{{ i + 1 }}. {{ item.name }}</li>
} @empty {
  <li>列表为空</li>
}

<!-- @switch -->
@switch (status) {
  @case ("loading") { <spinner /> }
  @case ("error") { <error /> }
  @default { <content /> }
}

五、依赖注入(DI)

Angular 的核心优势之一:

@Injectable({ providedIn: "root" })  // 应用级单例
export class AuthService {
  private user = signal<User | null>(null);

  login(credentials: Credentials): Observable<User> {
    return this.http.post<User>("/api/login", credentials).pipe(
      tap((user) => this.user.set(user))
    );
  }
}

@Component({ /* ... */ })
export class LoginComponent {
  // 自动注入,无需手动创建
  constructor(private auth: AuthService) {}
}

六、Signal vs RxJS

Angular 16+ 引入 Signals,与 RxJS 互补:

Signal RxJS Observable
读取 count() 同步 .subscribe() 异步
用途 组件状态 异步流、HTTP、WebSocket
示例 count = signal(0) http.get("/api")
转换 computed() .pipe(map())
// 互操作
const obs$ = this.http.get<User[]>("/api/users");   // Observable
const users = toSignal(obs$, { initialValue: [] }); // 转为 Signal

const count = signal(0);
const count$ = toObservable(count);                  // 转为 Observable

七、路由

const routes: Routes = [
  { path: "", component: HomeComponent },
  { path: "products", component: ProductListComponent },
  { path: "products/:id", component: ProductDetailComponent },
  {
    path: "admin",
    canActivate: [AuthGuard],                    // 路由守卫
    loadChildren: () => import("./admin/admin.routes"), // 懒加载
  },
  { path: "**", component: NotFoundComponent },  // 通配 404
];
<!-- router-outlet 是路由组件的渲染出口 -->
<router-outlet />

<!-- routerLink 声明式导航 -->
<a routerLink="/products" routerLinkActive="active">产品</a>

八、HTTP 客户端

import { HttpClient } from "@angular/common/http";

@Injectable({ providedIn: "root" })
export class ProductService {
  constructor(private http: HttpClient) {}

  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>("/api/products");
  }

  createProduct(data: Partial<Product>): Observable<Product> {
    return this.http.post<Product>("/api/products", data);
  }

  deleteProduct(id: number): Observable<void> {
    return this.http.delete<void>(`/api/products/${id}`);
  }
}

九、最佳实践

  1. 使用 Standalone Components(Angular 15+),告别 NgModule 样板
  2. Signals 优先于传统双向绑定,逐步替代 RxJS 在组件状态中的使用
  3. OnPush 变更检测changeDetection: ChangeDetectionStrategy.OnPush 提升性能
  4. Lazy Loading:每个功能模块独立懒加载
  5. track 函数@for 中始终提供 track 表达式

十、思考题

  1. Angular 的依赖注入与 React Context 有什么本质区别?
  2. 为什么 Angular 选择 RxJS 作为异步基础,而不是 Promise?
  3. Signals 会完全取代 RxJS 在 Angular 中的地位吗?

信息

路径
/tech-stacks/angular/tutorial/入门教程 - 企业级框架核心概念.md
更新时间
2026/5/31