Angular 生态完整指南
什么是 Angular
Angular 是由 Google 开发的一个完整的 TypeScript 框架。与 React 和 Vue 不同,Angular 是一个全功能框架,提供了开发企业级应用所需的所有工具和模式。
Angular 的核心特点:
┌─────────────────────────────────┐
│ 完整的框架 │
├─────────────────────────────────┤
│ ✅ 依赖注入(DI) │
│ ✅ 装饰器(Decorators) │
│ ✅ RxJS 响应式编程 │
│ ✅ 模块系统(Modules) │
│ ✅ 路由系统 │
│ ✅ 表单系统 │
│ ✅ HTTP 客户端 │
│ ✅ 测试框架 │
└─────────────────────────────────┘
1. 核心架构
1.1 模块系统
Angular 应用由模块组成。每个模块是一个用 @NgModule 装饰器标记的类。
// app.module.ts
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { AppComponent } from './app.component'
import { HomeComponent } from './pages/home.component'
import { RouterModule } from '@angular/router'
@NgModule({
// 声明该模块拥有的组件
declarations: [
AppComponent,
HomeComponent
],
// 导入其他模块的功能
imports: [
BrowserModule,
RouterModule.forRoot([
{ path: '', component: HomeComponent }
])
],
// 提供的服务(依赖注入)
providers: [
// 默认为单例,应用级别
],
// 启动组件
bootstrap: [AppComponent]
})
export class AppModule {}
1.2 组件和模板
// 组件定义
@Component({
selector: 'app-counter',
template: `
<div>
<p>Count: {{ count }}</p>
<button (click)="increment()">+1</button>
</div>
`,
styles: [`
div { padding: 20px; }
button { background: #007bff; color: white; }
`]
})
export class CounterComponent {
count = 0
increment() {
this.count++
}
}
2. 依赖注入(DI)系统
2.1 DI 基础
依赖注入是 Angular 的核心,允许类声明它们需要什么依赖,而不需要自己创建。
// service.ts - 服务定义
import { Injectable } from '@angular/core'
@Injectable({
providedIn: 'root' // 在根模块提供,应用级单例
})
export class UserService {
getUser(id: number) {
return { id, name: 'John', email: 'john@example.com' }
}
}
// component.ts - 组件注入服务
import { Component } from '@angular/core'
@Component({
selector: 'app-user',
template: `
<div>
<p>用户:{{ user?.name }}</p>
<p>邮箱:{{ user?.email }}</p>
</div>
`
})
export class UserComponent {
user: any
// 通过构造函数注入 UserService
constructor(private userService: UserService) {
this.user = this.userService.getUser(1)
}
}
2.2 DI 提供器
// 不同的提供器类型
// 1. 类提供器
providers: [
UserService // 简写方式,等同于 { provide: UserService, useClass: UserService }
]
// 2. 工厂提供器
providers: [
{
provide: 'USER_SERVICE',
useFactory: () => {
// 运行时决定返回什么
return new UserService()
}
}
]
// 3. 值提供器
const appConfig = { apiUrl: 'https://api.example.com' }
providers: [
{ provide: 'APP_CONFIG', useValue: appConfig }
]
// 4. 别名提供器
providers: [
OldUserService,
{ provide: NewUserService, useExisting: OldUserService }
]
// 使用 @Inject 获取值提供器
import { Inject } from '@angular/core'
constructor(@Inject('APP_CONFIG') config) {
console.log(config.apiUrl)
}
3. 装饰器(Decorators)
3.1 类装饰器
// @Component
@Component({
selector: 'app-button',
template: '<button><ng-content></ng-content></button>'
})
export class ButtonComponent {}
// @Directive
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow'
}
}
// @Injectable
@Injectable()
export class DataService {
constructor(private http: HttpClient) {}
}
// @NgModule
@NgModule({
declarations: [],
imports: [],
providers: []
})
export class FeatureModule {}
3.2 属性装饰器
@Component({
selector: 'app-list-item',
template: '<p>{{ title }} - ${{ price }}</p>'
})
export class ListItemComponent {
// 输入属性 - 接收父组件的值
@Input() title: string = ''
@Input() price: number = 0
// 输出属性 - 向父组件发送事件
@Output() selected = new EventEmitter<string>()
onClick() {
this.selected.emit(this.title)
}
}
// 使用
<app-list-item
[title]="'产品 A'"
[price]="99"
(selected)="onSelected($event)">
</app-list-item>
4. RxJS 响应式编程
4.1 Observable 基础
import { Observable } from 'rxjs'
// 创建 Observable
const observable = new Observable(subscriber => {
subscriber.next('值 1')
subscriber.next('值 2')
subscriber.complete()
})
// 订阅 Observable
observable.subscribe({
next: (value) => console.log(value),
error: (err) => console.error(err),
complete: () => console.log('完成')
})
// 从数组创建
import { of, from } from 'rxjs'
of(1, 2, 3).subscribe(v => console.log(v))
from([1, 2, 3]).subscribe(v => console.log(v))
4.2 常用操作符
import { map, filter, switchMap, debounceTime, tap } from 'rxjs/operators'
// 数据转换
source$.pipe(
map(x => x * 2),
filter(x => x > 5)
).subscribe(result => console.log(result))
// 搜索功能
searchInput$.pipe(
debounceTime(300), // 等待 300ms
map(term => this.searchService.search(term)),
switchMap(result => result) // 切换到最新搜索
).subscribe(results => {
this.results = results
})
// 调试
data$.pipe(
tap(value => console.log('值:', value)),
map(value => value * 2),
tap(value => console.log('处理后:', value))
).subscribe()
4.3 在 Angular 中的应用
// 数据流管理
@Injectable()
export class ProductService {
private products$ = this.http.get('/api/products').pipe(
map(data => data.products),
tap(products => console.log('产品加载:', products)),
catchError(err => {
console.error('错误:', err)
return of([])
})
)
constructor(private http: HttpClient) {}
getProducts() {
return this.products$
}
}
// 在组件中使用
@Component({
template: `
<div>
<div *ngFor="let product of products$ | async">
{{ product.name }} - ${{ product.price }}
</div>
</div>
`
})
export class ProductListComponent {
products$ = this.productService.getProducts()
constructor(private productService: ProductService) {}
}
5. 路由系统
5.1 基本路由
import { RouterModule, Routes } from '@angular/router'
const routes: Routes = [
{
path: '',
component: HomeComponent,
data: { title: '首页' }
},
{
path: 'about',
component: AboutComponent
},
{
path: 'product/:id',
component: ProductDetailComponent
},
// 重定向
{
path: 'old-page',
redirectTo: '/new-page'
},
// 懒加载
{
path: 'feature',
loadChildren: () => import('./feature/feature.module')
.then(m => m.FeatureModule)
},
// 通配符(必须最后)
{
path: '**',
component: NotFoundComponent
}
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
5.2 路由守卫
import { Injectable } from '@angular/core'
import { CanActivate, Router } from '@angular/router'
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate() {
if (this.authService.isLoggedIn()) {
return true
}
this.router.navigate(['/login'])
return false
}
}
// 使用守卫
const routes: Routes = [
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard]
}
]
6. 表单系统
6.1 模板驱动表单
@Component({
template: `
<form (ngSubmit)="submit(form)" #form="ngForm">
<input
name="username"
[(ngModel)]="user.username"
required
>
<input
name="email"
[(ngModel)]="user.email"
type="email"
required
>
<button type="submit">提交</button>
<p *ngIf="form.invalid">表单有效性:{{ form.valid }}</p>
</form>
`
})
export class LoginComponent {
user = { username: '', email: '' }
submit(form: NgForm) {
if (form.valid) {
console.log('提交:', this.user)
}
}
}
6.2 响应式表单
import { FormBuilder, FormGroup, Validators } from '@angular/forms'
@Component({
template: `
<form [formGroup]="form" (ngSubmit)="submit()">
<input formControlName="username">
<input formControlName="email" type="email">
<button type="submit" [disabled]="form.invalid">提交</button>
</form>
`
})
export class LoginComponent {
form: FormGroup
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
username: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
})
}
submit() {
console.log(this.form.value)
}
}
7. HTTP 通信
7.1 HttpClient
import { HttpClient, HttpErrorResponse } from '@angular/common/http'
import { catchError } from 'rxjs/operators'
import { throwError } from 'rxjs'
@Injectable()
export class ApiService {
constructor(private http: HttpClient) {}
// GET 请求
getUsers() {
return this.http.get<User[]>('/api/users')
}
// POST 请求
createUser(user: User) {
return this.http.post<User>('/api/users', user)
}
// PUT 请求
updateUser(id: number, user: User) {
return this.http.put<User>(`/api/users/${id}`, user)
}
// DELETE 请求
deleteUser(id: number) {
return this.http.delete(`/api/users/${id}`)
}
// 错误处理
private handleError(error: HttpErrorResponse) {
let errorMessage = '发生错误'
if (error.error instanceof ErrorEvent) {
errorMessage = error.error.message
} else {
errorMessage = `错误代码: ${error.status}`
}
return throwError(() => new Error(errorMessage))
}
}
7.2 HTTP 拦截器
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'
import { Injectable } from '@angular/core'
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
// 添加认证令牌
const authToken = localStorage.getItem('token')
if (authToken) {
const clonedReq = req.clone({
setHeaders: {
Authorization: `Bearer ${authToken}`
}
})
return next.handle(clonedReq)
}
return next.handle(req)
}
}
// 注册拦截器
@NgModule({
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}
]
})
export class AppModule {}
8. Angular 生态常用库
| 库 | 作用 | 说明 |
|---|---|---|
| @angular/material | UI 组件库 | 官方 Material Design 组件 |
| @ng-bootstrap/ng-bootstrap | Bootstrap 组件 | 原生 Angular 组件 |
| ngx-translate | 国际化 | 多语言支持 |
| ngx-pagination | 分页 | 表格分页 |
| ngx-toastr | 通知 | 轻提示 |
| angular-in-memory-web-api | 模拟 API | 开发测试 |
| cypress | E2E 测试 | 端到端测试 |
| karma + jasmine | 单元测试 | 默认测试框架 |
9. Angular 最佳实践
// ✅ 最佳实践清单
// 1. 使用强类型
interface User {
id: number
name: string
email: string
}
// 2. 使用 OnPush 变更检测提高性能
@Component({
selector: 'app-user',
template: '<p>{{ user.name }}</p>',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserComponent {
@Input() user: User
}
// 3. 适当取消订阅避免内存泄漏
export class DataComponent implements OnDestroy {
private destroy$ = new Subject<void>()
ngOnInit() {
this.data$
.pipe(takeUntil(this.destroy$))
.subscribe(data => this.data = data)
}
ngOnDestroy() {
this.destroy$.next()
this.destroy$.complete()
}
}
// 4. 使用异步管道简化
@Component({
template: '<p>{{ data$ | async }}</p>'
})
export class DataComponent {
data$ = this.dataService.getData()
constructor(private dataService: DataService) {}
}
// 5. 分离关注点
// ✅ 服务处理数据,组件处理展示
@Injectable()
export class UserService {
getUsers() { return this.http.get<User[]>('/api/users') }
}
@Component({
template: '<div *ngFor="let user of users">{{ user.name }}</div>'
})
export class UserListComponent {
users: User[] = []
constructor(private userService: UserService) {
this.userService.getUsers().subscribe(users => this.users = users)
}
}
10. Angular vs React vs Vue
| 特性 | Angular | React | Vue |
|---|---|---|---|
| 学习曲线 | 陡 | 中 | 平 |
| 框架完整度 | 完全 | 最小 | 中等 |
| 性能 | 良好 | 优秀 | 优秀 |
| 生态 | 完整 | 最丰富 | 良好 |
| 适用场景 | 大型企业应用 | 各种规模 | 中小型项目 |
| 社区 | 较小 | 最大 | 中等 |
| 就业需求 | 中等 | 最高 | 中等 |
总结
Angular 作为一个完整的框架:
- ✅ 提供了开发大型应用所需的所有工具
- ✅ 强大的依赖注入系统
- ✅ 完整的路由和表单系统
- ✅ RxJS 响应式编程
- ❌ 学习曲线陡峭
- ❌ 对小型项目过度设计
Angular 特别适合:
- 大型企业级应用
- 需要强类型和模块化的项目
- 团队已有 Java 或 .NET 背景


