09. Angular框架和TypeScript
📋 目录
Angular架构深入
Angular 是一个完整的企业级前端框架,提供了从开发到部署的完整解决方案,特别适合大型复杂应用的开发。
Angular核心概念
核心构建块对比
构建块 | 作用 | 装饰器 | 使用场景 |
---|---|---|---|
Component | UI组件 | @Component | 页面元素、可复用组件 |
Service | 业务逻辑 | @Injectable | 数据处理、API调用 |
Directive | DOM操作 | @Directive | 行为增强、DOM修改 |
Pipe | 数据转换 | @Pipe | 数据格式化、过滤 |
Module | 功能模块 | @NgModule | 功能组织、依赖管理 |
组件示例
// 1. 基础组件
@Component({
selector: 'app-user-card',
template: `
<div class="user-card" [class.active]="isActive">
<img [src]="user.avatar" [alt]="user.name">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<button (click)="onEdit()" [disabled]="!canEdit">编辑</button>
<button (click)="onDelete()" class="danger">删除</button>
</div>
`,
styleUrls: ['./user-card.component.scss']
})
export class UserCardComponent implements OnInit, OnDestroy {
@Input() user!: User;
@Input() canEdit: boolean = true;
@Input() isActive: boolean = false;
@Output() edit = new EventEmitter<User>();
@Output() delete = new EventEmitter<string>();
private destroy$ = new Subject<void>();
ngOnInit(): void {
console.log('UserCard component initialized');
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
onEdit(): void {
this.edit.emit(this.user);
}
onDelete(): void {
this.delete.emit(this.user.id);
}
}
服务示例
// 2. 数据服务
export interface User {
id: string;
name: string;
email: string;
avatar: string;
role: 'admin' | 'user';
}
@Injectable({
providedIn: 'root'
})
export class UserService {
private readonly apiUrl = '/api/users';
private usersSubject = new BehaviorSubject<User[]>([]);
public users$ = this.usersSubject.asObservable();
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl).pipe(
tap(users => this.usersSubject.next(users)),
catchError(this.handleError)
);
}
createUser(user: Omit<User, 'id'>): Observable<User> {
return this.http.post<User>(this.apiUrl, user).pipe(
tap(newUser => {
const currentUsers = this.usersSubject.value;
this.usersSubject.next([...currentUsers, newUser]);
}),
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse): Observable<never> {
const errorMessage = error.error instanceof ErrorEvent
? `客户端错误: ${error.error.message}`
: `服务端错误: ${error.status} - ${error.message}`;
console.error(errorMessage);
return throwError(() => new Error(errorMessage));
}
}
指令和管道示例
// 3. 自定义指令
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() appHighlight = '';
@Input() defaultColor = 'yellow';
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.appHighlight || this.defaultColor);
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight('');
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
// 4. 自定义管道
@Pipe({
name: 'truncate',
pure: true
})
export class TruncatePipe implements PipeTransform {
transform(value: string, limit: number = 50, trail: string = '...'): string {
if (!value) return '';
return value.length > limit ? value.substring(0, limit) + trail : value;
}
}
// 使用:<p>{{ longText | truncate:100:'...' }}</p>
模块系统
模块类型对比
模块类型 | 作用 | 特点 | 使用场景 |
---|---|---|---|
特性模块 | 组织相关功能 | 包含组件、服务、路由 | 用户管理、订单管理 |
共享模块 | 共享通用组件 | 导出常用组件和指令 | UI组件库、工具函数 |
核心模块 | 全局单例服务 | 只导入一次 | 认证、拦截器 |
懒加载模块 | 按需加载 | 减少初始包大小 | 大型功能模块 |
模块示例
// 1. 特性模块
@NgModule({
declarations: [
UserListComponent,
UserCardComponent,
UserFormComponent,
TruncatePipe,
HighlightDirective
],
imports: [
CommonModule,
ReactiveFormsModule,
RouterModule.forChild([
{ path: '', component: UserListComponent },
{ path: 'create', component: UserFormComponent },
{ path: ':id/edit', component: UserFormComponent }
])
],
providers: [UserService],
exports: [UserCardComponent, TruncatePipe]
})
export class UserModule {}
// 2. 共享模块
@NgModule({
declarations: [
LoadingSpinnerComponent,
ConfirmDialogComponent,
ToastComponent
],
imports: [CommonModule, MaterialModule],
exports: [
CommonModule,
MaterialModule,
LoadingSpinnerComponent,
ConfirmDialogComponent,
ToastComponent
]
})
export class SharedModule {}
// 3. 核心模块(单例)
@NgModule({
providers: [
AuthService,
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }
]
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error('CoreModule已经加载,只能在AppModule中导入一次');
}
}
}
模块最佳实践
- 特性模块:按业务功能组织,包含相关的组件、服务和路由
- 共享模块:导出通用组件和第三方模块,避免重复导入
- 核心模块:包含全局单例服务,确保只导入一次
- 懒加载:大型功能模块使用懒加载,提升应用启动性能
TypeScript在Angular中的应用
高级类型系统
⚠️
TypeScript的强类型系统是Angular的核心优势之一,能够在编译时发现错误,提高代码质量。
TypeScript特性在Angular中的应用
特性 | 用途 | 优势 | 示例 |
---|---|---|---|
接口定义 | 数据结构约束 | 编译时类型检查 | interface User |
泛型 | 类型参数化 | 代码复用,类型安全 | ApiResponse<T> |
联合类型 | 多种可能类型 | 精确的类型约束 | 'admin' | 'user' |
映射类型 | 类型转换 | 基于现有类型生成新类型 | Partial<T> |
类型守卫 | 运行时类型检查 | 类型安全的类型缩窄 | obj is User |
基础类型定义
// 1. 接口和类型定义
export interface ApiResponse<T> {
data: T;
message: string;
success: boolean;
timestamp: number;
}
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
export type UserRole = 'admin' | 'moderator' | 'user';
export type UserStatus = 'active' | 'inactive' | 'pending';
export interface User {
id: string;
name: string;
email: string;
role: UserRole;
status: UserStatus;
createdAt: Date;
updatedAt: Date;
profile?: UserProfile;
}
泛型服务
// 2. 泛型API服务
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private http: HttpClient) {}
get<T>(url: string): Observable<ApiResponse<T>> {
return this.http.get<ApiResponse<T>>(url);
}
post<T, U = any>(url: string, data: U): Observable<ApiResponse<T>> {
return this.http.post<ApiResponse<T>>(url, data);
}
getPaginated<T>(
url: string,
params: { page: number; limit: number }
): Observable<PaginatedResponse<T>> {
const httpParams = new HttpParams()
.set('page', params.page.toString())
.set('limit', params.limit.toString());
return this.http.get<PaginatedResponse<T>>(url, { params: httpParams });
}
}
实用类型和类型守卫
// 3. 实用类型示例
export type CreateUserDto = Omit<User, 'id' | 'createdAt' | 'updatedAt'>;
export type UpdateUserDto = Partial<Pick<User, 'name' | 'email' | 'role' | 'status'>>;
export type UserSummary = Pick<User, 'id' | 'name' | 'email' | 'role'>;
// 4. 类型守卫
export function isUser(obj: any): obj is User {
return obj &&
typeof obj.id === 'string' &&
typeof obj.name === 'string' &&
typeof obj.email === 'string' &&
['admin', 'moderator', 'user'].includes(obj.role);
}
// 5. 使用类型守卫
@Component({
selector: 'app-user-detail',
template: `
<div *ngIf="user">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
</div>
`
})
export class UserDetailComponent {
user: User | null = null;
loadUser(data: unknown): void {
if (isUser(data)) {
this.user = data; // TypeScript知道这里data是User类型
} else {
console.error('Invalid user data:', data);
}
}
}
TypeScript最佳实践
- 严格模式:启用
strict: true
获得最佳类型检查 - 接口优于类型别名:对于对象结构使用interface
- 泛型约束:使用
extends
约束泛型参数 - 类型守卫:运行时类型检查确保类型安全
- 实用类型:充分利用内置实用类型简化类型定义
依赖注入系统
高级依赖注入
依赖注入提供者类型
提供者类型 | 语法 | 用途 | 示例 |
---|---|---|---|
类提供者 | useClass | 提供类实例 | { provide: Service, useClass: MockService } |
值提供者 | useValue | 提供静态值 | { provide: CONFIG, useValue: config } |
工厂提供者 | useFactory | 动态创建实例 | { provide: Logger, useFactory: createLogger } |
别名提供者 | useExisting | 引用现有提供者 | { provide: NewService, useExisting: OldService } |
注入令牌和配置
// 1. 注入令牌
import { InjectionToken } from '@angular/core';
export const API_CONFIG = new InjectionToken<ApiConfig>('api.config');
export const FEATURE_FLAGS = new InjectionToken<FeatureFlags>('feature.flags');
export interface ApiConfig {
baseUrl: string;
timeout: number;
retryAttempts: number;
}
export interface FeatureFlags {
enableNewUI: boolean;
enableAnalytics: boolean;
enableBetaFeatures: boolean;
}
// 2. 工厂提供者
export function createApiService(http: HttpClient, config: ApiConfig): ApiService {
return new ApiService(http, config);
}
export function createLogger(isDevelopment: boolean): Logger {
return isDevelopment ? new ConsoleLogger() : new RemoteLogger();
}
模块配置示例
// 3. 模块配置
@NgModule({
providers: [
{
provide: API_CONFIG,
useValue: {
baseUrl: 'https://api.example.com',
timeout: 5000,
retryAttempts: 3
}
},
{
provide: FEATURE_FLAGS,
useFactory: () => ({
enableNewUI: environment.production,
enableAnalytics: true,
enableBetaFeatures: !environment.production
})
},
{
provide: ApiService,
useFactory: createApiService,
deps: [HttpClient, API_CONFIG]
}
]
})
export class AppModule {}
注入装饰器
// 4. 注入装饰器使用
@Component({
selector: 'app-user-list',
providers: [
{ provide: UserService, useClass: CachedUserService }
]
})
export class UserListComponent {
constructor(
private userService: UserService, // 使用CachedUserService
@Inject(FEATURE_FLAGS) private featureFlags: FeatureFlags,
@Optional() private analytics: AnalyticsService, // 可选依赖
@Self() private localService: LocalService // 只在当前注入器查找
) {}
}
依赖注入最佳实践
- 使用接口:定义服务契约,便于测试和替换
- 注入令牌:为非类依赖提供类型安全的注入
- 工厂函数:复杂对象创建逻辑
- 层级注入:合理利用注入器层级,避免不必要的单例
- 可选依赖:使用
@Optional()
处理可选服务
RxJS响应式编程
Observable模式深入
RxJS是Angular的核心依赖,掌握响应式编程对于构建高质量的Angular应用至关重要。
常用RxJS操作符
操作符类型 | 操作符 | 作用 | 使用场景 |
---|---|---|---|
创建 | of , from , interval | 创建Observable | 数据源创建 |
转换 | map , switchMap , mergeMap | 数据转换 | 数据处理、API调用 |
过滤 | filter , debounceTime , distinctUntilChanged | 数据过滤 | 搜索、去重 |
组合 | combineLatest , merge , zip | 流组合 | 状态管理 |
错误处理 | catchError , retry , retryWhen | 错误处理 | 异常恢复 |
搜索服务示例
// 1. 搜索服务
@Injectable({
providedIn: 'root'
})
export class SearchService {
private searchTerms = new Subject<string>();
// 搜索结果流
public searchResults$ = this.searchTerms.pipe(
debounceTime(300), // 防抖
distinctUntilChanged(), // 去重
filter(term => term.length >= 2), // 过滤短查询
switchMap(term =>
this.apiService.search(term).pipe(
catchError(error => {
console.error('搜索错误:', error);
return of([]); // 返回空数组作为默认值
})
)
),
shareReplay(1) // 缓存最新结果
);
search(term: string): void {
this.searchTerms.next(term);
}
}
状态管理服务
// 2. 状态管理服务
@Injectable({
providedIn: 'root'
})
export class UserStateService {
private usersSubject = new BehaviorSubject<User[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
private errorSubject = new BehaviorSubject<string | null>(null);
public users$ = this.usersSubject.asObservable();
public loading$ = this.loadingSubject.asObservable();
public error$ = this.errorSubject.asObservable();
// 组合状态
public state$ = combineLatest([
this.users$,
this.loading$,
this.error$
]).pipe(
map(([users, loading, error]) => ({
users,
loading,
error,
hasUsers: users.length > 0,
isEmpty: users.length === 0 && !loading && !error
}))
);
loadUsers(): void {
this.loadingSubject.next(true);
this.errorSubject.next(null);
this.userService.getUsers().pipe(
finalize(() => this.loadingSubject.next(false))
).subscribe({
next: users => this.usersSubject.next(users),
error: error => this.errorSubject.next(error.message)
});
}
}
RxJS最佳实践
- 内存泄漏防护:使用
takeUntil
或async
管道自动取消订阅 - 错误处理:使用
catchError
处理错误,避免流中断 - 性能优化:使用
shareReplay
缓存结果,避免重复请求 - 操作符选择:
switchMap
用于搜索,mergeMap
用于并发请求 - 状态管理:使用
BehaviorSubject
管理组件状态
Angular企业级开发
高级RxJS模式
// 1. 自定义操作符
export function retryWithBackoff(maxRetries: number = 3, baseDelay: number = 1000) {
return <T>(source: Observable<T>) => source.pipe(
retryWhen(errors =>
errors.pipe(
scan((retryCount, error) => {
if (retryCount >= maxRetries) {
throw error;
}
return retryCount + 1;
}, 0),
delay(baseDelay),
tap(retryCount => console.log(`重试第 ${retryCount} 次`))
)
)
);
}
// 2. 缓存操作符
export function cacheWithExpiry<T>(ttl: number = 5000) {
return (source: Observable<T>) => {
let cache: { value: T; timestamp: number } | null = null;
return new Observable<T>(observer => {
if (cache && Date.now() - cache.timestamp < ttl) {
observer.next(cache.value);
observer.complete();
return;
}
return source.subscribe({
next: value => {
cache = { value, timestamp: Date.now() };
observer.next(value);
},
error: error => observer.error(error),
complete: () => observer.complete()
});
});
};
}
// 使用自定义操作符
@Injectable({
providedIn: 'root'
})
export class DataService {
getData(): Observable<any> {
return this.http.get('/api/data').pipe(
retryWithBackoff(3, 1000),
cacheWithExpiry(10000),
catchError(error => {
console.error('获取数据失败:', error);
return throwError(() => error);
})
);
}
}
// 4. 响应式表单
@Component({
selector: 'app-user-form',
template: `
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="name">姓名</label>
<input
id="name"
type="text"
formControlName="name"
[class.invalid]="nameControl.invalid && nameControl.touched">
<div *ngIf="nameControl.invalid && nameControl.touched" class="error">
<span *ngIf="nameControl.errors?.['required']">姓名是必填项</span>
<span *ngIf="nameControl.errors?.['minlength']">姓名至少2个字符</span>
</div>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input
id="email"
type="email"
formControlName="email"
[class.invalid]="emailControl.invalid && emailControl.touched">
<div *ngIf="emailControl.invalid && emailControl.touched" class="error">
<span *ngIf="emailControl.errors?.['required']">邮箱是必填项</span>
<span *ngIf="emailControl.errors?.['email']">邮箱格式不正确</span>
<span *ngIf="emailControl.errors?.['emailTaken']">邮箱已被使用</span>
</div>
</div>
<button type="submit" [disabled]="userForm.invalid || submitting">
{{ submitting ? '提交中...' : '提交' }}
</button>
</form>
`
})
export class UserFormComponent implements OnInit, OnDestroy {
userForm!: FormGroup;
submitting = false;
private destroy$ = new Subject<void>();
constructor(
private fb: FormBuilder,
private userService: UserService
) {}
ngOnInit(): void {
this.createForm();
this.setupFormValidation();
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
get nameControl() { return this.userForm.get('name')!; }
get emailControl() { return this.userForm.get('email')!; }
private createForm(): void {
this.userForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email], [this.emailValidator.bind(this)]]
});
}
private setupFormValidation(): void {
// 实时验证
this.userForm.valueChanges.pipe(
debounceTime(300),
takeUntil(this.destroy$)
).subscribe(value => {
console.log('表单值变化:', value);
});
// 邮箱字段变化时的特殊处理
this.emailControl.valueChanges.pipe(
debounceTime(500),
distinctUntilChanged(),
takeUntil(this.destroy$)
).subscribe(email => {
if (email && this.emailControl.valid) {
console.log('邮箱验证通过:', email);
}
});
}
private emailValidator(control: AbstractControl): Observable<ValidationErrors | null> {
if (!control.value) {
return of(null);
}
return this.userService.checkEmailExists(control.value).pipe(
map(exists => exists ? { emailTaken: true } : null),
catchError(() => of(null))
);
}
onSubmit(): void {
if (this.userForm.valid) {
this.submitting = true;
this.userService.createUser(this.userForm.value).pipe(
finalize(() => this.submitting = false),
takeUntil(this.destroy$)
).subscribe({
next: user => {
console.log('用户创建成功:', user);
this.userForm.reset();
},
error: error => {
console.error('用户创建失败:', error);
}
});
}
}
}
企业级架构模式
// 1. 特性模块架构
// shared/shared.module.ts
@NgModule({
declarations: [
LoadingComponent,
ConfirmDialogComponent,
DataTableComponent
],
imports: [
CommonModule,
MaterialModule,
ReactiveFormsModule
],
exports: [
LoadingComponent,
ConfirmDialogComponent,
DataTableComponent,
MaterialModule,
ReactiveFormsModule
]
})
export class SharedModule {}
// core/core.module.ts
@NgModule({
providers: [
AuthService,
ErrorHandlerService,
LoggerService,
{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
},
{
provide: HTTP_INTERCEPTORS,
useClass: ErrorInterceptor,
multi: true
}
]
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
if (parentModule) {
throw new Error('CoreModule已经加载,只能在AppModule中导入一次');
}
}
}
// features/user/user.module.ts
@NgModule({
declarations: [
UserListComponent,
UserDetailComponent,
UserFormComponent
],
imports: [
CommonModule,
SharedModule,
UserRoutingModule
]
})
export class UserModule {}
// 2. 状态管理架构
// store/user/user.state.ts
export interface UserState {
users: User[];
selectedUser: User | null;
loading: boolean;
error: string | null;
}
export const initialUserState: UserState = {
users: [],
selectedUser: null,
loading: false,
error: null
};
// store/user/user.actions.ts
export const UserActions = createActionGroup({
source: 'User',
events: {
'Load Users': emptyProps(),
'Load Users Success': props<{ users: User[] }>(),
'Load Users Failure': props<{ error: string }>(),
'Select User': props<{ userId: string }>(),
'Create User': props<{ user: Partial<User> }>(),
'Update User': props<{ user: User }>(),
'Delete User': props<{ userId: string }>()
}
});
// store/user/user.reducer.ts
export const userReducer = createReducer(
initialUserState,
on(UserActions.loadUsers, (state) => ({
...state,
loading: true,
error: null
})),
on(UserActions.loadUsersSuccess, (state, { users }) => ({
...state,
users,
loading: false
})),
on(UserActions.loadUsersFailure, (state, { error }) => ({
...state,
loading: false,
error
})),
on(UserActions.selectUser, (state, { userId }) => ({
...state,
selectedUser: state.users.find(user => user.id === userId) || null
}))
);
// store/user/user.effects.ts
@Injectable()
export class UserEffects {
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUsers),
switchMap(() =>
this.userService.getUsers().pipe(
map(users => UserActions.loadUsersSuccess({ users })),
catchError(error => of(UserActions.loadUsersFailure({
error: error.message
})))
)
)
)
);
createUser$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.createUser),
switchMap(({ user }) =>
this.userService.createUser(user).pipe(
map(() => UserActions.loadUsers()),
catchError(error => of(UserActions.loadUsersFailure({
error: error.message
})))
)
)
)
);
constructor(
private actions$: Actions,
private userService: UserService
) {}
}
// 3. 企业级表单管理
@Injectable({
providedIn: 'root'
})
export class FormBuilderService {
createUserForm(): FormGroup {
return this.fb.group({
personalInfo: this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(2)]],
lastName: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
phone: ['', [Validators.pattern(/^\d{10,11}$/)]]
}),
address: this.fb.group({
street: ['', Validators.required],
city: ['', Validators.required],
state: ['', Validators.required],
zipCode: ['', [Validators.required, Validators.pattern(/^\d{5}$/)]]
}),
preferences: this.fb.group({
newsletter: [false],
notifications: [true],
theme: ['light']
})
});
}
constructor(private fb: FormBuilder) {}
}
// 4. 权限管理系统
@Injectable({
providedIn: 'root'
})
export class PermissionService {
private permissions$ = new BehaviorSubject<string[]>([]);
hasPermission(permission: string): Observable<boolean> {
return this.permissions$.pipe(
map(permissions => permissions.includes(permission))
);
}
hasAnyPermission(permissions: string[]): Observable<boolean> {
return this.permissions$.pipe(
map(userPermissions =>
permissions.some(permission => userPermissions.includes(permission))
)
);
}
setPermissions(permissions: string[]): void {
this.permissions$.next(permissions);
}
}
@Directive({
selector: '[appHasPermission]'
})
export class HasPermissionDirective implements OnInit, OnDestroy {
@Input() appHasPermission!: string;
private destroy$ = new Subject<void>();
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private permissionService: PermissionService
) {}
ngOnInit(): void {
this.permissionService.hasPermission(this.appHasPermission).pipe(
takeUntil(this.destroy$)
).subscribe(hasPermission => {
if (hasPermission) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
性能优化和最佳实践
⚠️
Angular应用的性能优化需要从多个维度考虑,包括变更检测、懒加载、预加载策略等。
变更检测优化
// 1. OnPush变更检测策略
@Component({
selector: 'app-user-card',
template: `
<div class="user-card">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
<button (click)="onEdit()">编辑</button>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserCardComponent {
@Input() user!: User;
@Output() edit = new EventEmitter<User>();
constructor(private cdr: ChangeDetectorRef) {}
onEdit(): void {
this.edit.emit(this.user);
}
// 手动触发变更检测
updateUser(user: User): void {
this.user = user;
this.cdr.markForCheck();
}
}
// 2. TrackBy函数优化
@Component({
selector: 'app-user-list',
template: `
<div class="user-list">
<app-user-card
*ngFor="let user of users; trackBy: trackByUserId"
[user]="user"
(edit)="onEditUser($event)">
</app-user-card>
</div>
`
})
export class UserListComponent {
@Input() users: User[] = [];
trackByUserId(index: number, user: User): string {
return user.id;
}
onEditUser(user: User): void {
// 编辑用户逻辑
}
}
// 3. 异步管道优化
@Component({
selector: 'app-dashboard',
template: `
<div class="dashboard">
<div *ngIf="users$ | async as users">
<app-user-list [users]="users"></app-user-list>
</div>
<div *ngIf="loading$ | async" class="loading">
加载中...
</div>
</div>
`
})
export class DashboardComponent {
users$ = this.store.select(selectUsers);
loading$ = this.store.select(selectUsersLoading);
constructor(private store: Store) {}
}
// 4. 虚拟滚动
@Component({
selector: 'app-virtual-list',
template: `
<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<div *cdkVirtualFor="let item of items; trackBy: trackByFn">
{{ item.name }}
</div>
</cdk-virtual-scroll-viewport>
`,
styles: [`
.viewport {
height: 400px;
width: 100%;
}
`]
})
export class VirtualListComponent {
@Input() items: any[] = [];
trackByFn(index: number, item: any): any {
return item.id;
}
}
懒加载和预加载策略
// 1. 路由懒加载
const routes: Routes = [
{
path: 'users',
loadChildren: () => import('./features/users/users.module').then(m => m.UsersModule)
},
{
path: 'products',
loadChildren: () => import('./features/products/products.module').then(m => m.ProductsModule)
},
{
path: 'orders',
loadChildren: () => import('./features/orders/orders.module').then(m => m.OrdersModule)
}
];
// 2. 自定义预加载策略
@Injectable()
export class CustomPreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
// 只预加载标记为preload的路由
if (route.data && route.data['preload']) {
console.log('预加载路由:', route.path);
return load();
}
return of(null);
}
}
// 路由配置
const routes: Routes = [
{
path: 'users',
loadChildren: () => import('./features/users/users.module').then(m => m.UsersModule),
data: { preload: true }
},
{
path: 'admin',
loadChildren: () => import('./features/admin/admin.module').then(m => m.AdminModule),
data: { preload: false }
}
];
@NgModule({
imports: [RouterModule.forRoot(routes, {
preloadingStrategy: CustomPreloadingStrategy
})],
providers: [CustomPreloadingStrategy]
})
export class AppRoutingModule {}
// 3. 组件懒加载
@Component({
selector: 'app-lazy-component',
template: `
<div>
<button (click)="loadComponent()" *ngIf="!componentLoaded">
加载组件
</button>
<ng-container #dynamicComponent></ng-container>
</div>
`
})
export class LazyComponentComponent {
@ViewChild('dynamicComponent', { read: ViewContainerRef })
dynamicComponent!: ViewContainerRef;
componentLoaded = false;
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
async loadComponent(): Promise<void> {
const { HeavyComponent } = await import('./heavy/heavy.component');
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(HeavyComponent);
this.dynamicComponent.createComponent(componentFactory);
this.componentLoaded = true;
}
}
内存管理和性能监控
// 1. 内存泄漏防护
@Component({
selector: 'app-memory-safe',
template: `<div>{{ data$ | async }}</div>`
})
export class MemorySafeComponent implements OnInit, OnDestroy {
data$!: Observable<any>;
private destroy$ = new Subject<void>();
ngOnInit(): void {
// 使用takeUntil防止内存泄漏
this.data$ = this.dataService.getData().pipe(
takeUntil(this.destroy$)
);
// 定时器也需要清理
interval(1000).pipe(
takeUntil(this.destroy$)
).subscribe(value => {
console.log('定时器值:', value);
});
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
}
// 2. 性能监控服务
@Injectable({
providedIn: 'root'
})
export class PerformanceMonitorService {
private performanceObserver?: PerformanceObserver;
startMonitoring(): void {
if ('PerformanceObserver' in window) {
this.performanceObserver = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.entryType === 'navigation') {
this.logNavigationTiming(entry as PerformanceNavigationTiming);
} else if (entry.entryType === 'paint') {
this.logPaintTiming(entry);
}
});
});
this.performanceObserver.observe({
entryTypes: ['navigation', 'paint', 'largest-contentful-paint']
});
}
}
private logNavigationTiming(entry: PerformanceNavigationTiming): void {
console.log('导航性能指标:', {
domContentLoaded: entry.domContentLoadedEventEnd - entry.domContentLoadedEventStart,
loadComplete: entry.loadEventEnd - entry.loadEventStart,
firstByte: entry.responseStart - entry.requestStart
});
}
private logPaintTiming(entry: PerformanceEntry): void {
console.log(`${entry.name}: ${entry.startTime}ms`);
}
stopMonitoring(): void {
if (this.performanceObserver) {
this.performanceObserver.disconnect();
}
}
}
// 3. Bundle分析和优化
// angular.json配置
{
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
}
Angular提供了完整的企业级开发解决方案,通过TypeScript、依赖注入和RxJS的强大组合,能够构建大型、可维护的前端应用。
📚 参考学习资料
📖 官方文档
- Angular 官方文档 - Angular权威学习资源
- Angular API 参考 - 完整API文档
- TypeScript 官方文档 - TypeScript语言文档
- RxJS 官方文档 - 响应式编程库文档
🎓 优质教程
- Angular 官方教程 - 官方英雄之旅教程
- Angular University - Angular专业课程平台
- Angular in Depth - Angular深度技术文章
🛠️ 实践项目
- Angular CLI - 官方脚手架工具
- Angular Material - 官方UI组件库
- NgRx - Angular状态管理库
🔧 开发工具
- Angular DevTools - 官方调试工具
- Angular Language Service - VS Code扩展
- Nx - 企业级开发工具
- Compodoc - 文档生成工具
📝 深入阅读
- Angular Architecture - 架构指南
- Angular Performance - 性能优化清单
- Angular Security - 安全最佳实践
💡 学习建议:建议从Angular CLI开始创建项目,学习组件和服务的基本概念,然后深入TypeScript和RxJS,最后掌握企业级开发模式。
Last updated on