1. Angular 架构概述
1.1 核心概念
1)模块化架构 (NgModule)。
2)组件化开发。
3)依赖注入系统。
4)单向数据流。
5)TypeScript 支持。
1.2 平台支持
1)Web 应用 (浏览器)。
2)移动应用 (Ionic + Angular)。
3)桌面应用 (Electron + Angular)。
4)服务端渲染 (Angular Universal)。
2. 模块系统 (NgModule)
2.1 模块定义
TypeScript
@NgModule({
declarations: [AppComponent, UserComponent], // 组件、指令、管道
imports: [BrowserModule, HttpClientModule], // 导入其他模块
providers: [UserService, AuthService], // 服务提供者
bootstrap: [AppComponent] // 根组件
})
export class AppModule { }
2.2 模块类型
1)根模块 (AppModule)
2)特性模块 (FeatureModule)
3)共享模块 (SharedModule)
4)核心模块 (CoreModule)
5)路由模块 (RoutingModule)
3. 组件系统
3.1 组件结构
TypeScript
@Component({
selector: 'app-user',
template: `<h1>{{user.name}}</h1>`,
styleUrls: ['./user.component.css'],
providers: [UserService]
})
export class UserComponent implements OnInit {
@Input() user: User;
@Output() userSelected = new EventEmitter<User>();
constructor(private userService: UserService) {}
ngOnInit(): void {
// 初始化逻辑
}
}
3.2 组件生命周期钩子
TypeScript
export class UserComponent implements
OnInit, // 初始化
OnDestroy, // 销毁
OnChanges, // 输入属性变化
AfterViewInit, // 视图初始化后
AfterContentInit // 内容投影后
{
ngOnInit() { /* 组件初始化 */ }
ngOnChanges(changes: SimpleChanges) { /* 输入属性变化 */ }
ngAfterViewInit() { /* 视图初始化后 */ }
ngOnDestroy() { /* 组件销毁前清理 */ }
}
3.3 视图封装模式
1)Emulated (默认): 样式封装。
2)Native: 使用 Shadow DOM。
3)None: 全局样式。
4. 模板与数据绑定
4.1 数据绑定类型
html
<!-- 插值 -->
<h1>{{title}}</h1>
<!-- 属性绑定 -->
<img [src]="imageUrl" [alt]="description">
<!-- 事件绑定 -->
<button (click)="onSave()">保存</button>
<!-- 双向绑定 -->
<input [(ngModel)]="userName">
<!-- 样式绑定 -->
<div [class.active]="isActive" [style.color]="textColor">
4.2 内置指令
html
<!-- 结构指令 -->
<div *ngIf="isVisible">条件显示</div>
<li *ngFor="let item of items">{{item.name}}</li>
<div [ngSwitch]="status">
<span *ngSwitchCase="'active'">活跃</span>
<span *ngSwitchDefault>非活跃</span>
</div>
<!-- 属性指令 -->
<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">
<div [ngStyle]="{'font-size': fontSize + 'px'}">
<div [ngModel]="value" (ngModelChange)="onChange($event)">
4.3 模板引用变量
html
<input #emailInput type="email">
<button (click)="validate(emailInput.value)">验证</button>
5. 服务与依赖注入
5.1 服务创建
TypeScript
@Injectable({
providedIn: 'root' // 根注入器
})
export class UserService {
private apiUrl = '/api/users';
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl);
}
}
5.2 依赖注入层次
1)根注入器 (全局单例)。
2)模块注入器 (模块级别)。
3)组件注入器 (组件级别)。
5.3 注入令牌
TypeScript
// 字符串令牌
export const API_URL = new InjectionToken<string>('api.url');
// 在模块中提供
providers: [{ provide: API_URL, useValue: 'https://api.example.com' }]
// 在服务中注入
constructor(@Inject(API_URL) private apiUrl: string) {}
6. 路由系统
6.1 路由配置
TypeScript
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UserListComponent },
{ path: 'users/:id', component: UserDetailComponent },
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule) },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
6.2 路由导航
TypeScript
export class UserComponent {
constructor(private router: Router, private route: ActivatedRoute) {}
navigateToUser(id: number) {
// 编程式导航
this.router.navigate(['/users', id]);
// 带参数导航
this.router.navigate(['/users'], { queryParams: { page: 1 } });
}
ngOnInit() {
// 获取路由参数
this.route.params.subscribe(params => {
this.userId = params['id'];
});
}
}
6.3 路由守卫
TypeScript
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (this.authService.isLoggedIn()) {
return true;
} else {
this.router.navigate(['/login']);
return false;
}
}
}
7. 表单处理
7.1 模板驱动表单
html
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
<input
name="username"
ngModel
#username="ngModel"
required
minlength="3">
<div *ngIf="username.invalid && username.touched">
<div *ngIf="username.errors?.['required']">用户名必填</div>
<div *ngIf="username.errors?.['minlength']">用户名至少3位</div>
</div>
<button type="submit" [disabled]="userForm.invalid">提交</button>
</form>
7.2 响应式表单
TypeScript
export class UserFormComponent {
userForm = new FormGroup({
username: new FormControl('', [Validators.required, Validators.minLength(3)]),
email: new FormControl('', [Validators.required, Validators.email]),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl('')
})
});
onSubmit() {
if (this.userForm.valid) {
console.log(this.userForm.value);
}
}
// 在模板中使用
// <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
// <input formControlName="username">
// </form>
}
8. HTTP 客户端
8.1 HTTP 服务
TypeScript
@Injectable()
export class DataService {
constructor(private http: HttpClient) {}
// GET 请求
getUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users');
}
// POST 请求
createUser(user: User): Observable<User> {
return this.http.post<User>('/api/users', user);
}
// 带选项的请求
searchUsers(term: string): Observable<User[]> {
const options = {
params: new HttpParams().set('search', term)
};
return this.http.get<User[]>('/api/users/search', options);
}
}
8.2 错误处理
TypeScript
getUsers(): Observable<User[]> {
return this.http.get<User[]>('/api/users').pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// 客户端错误
console.error('客户端错误:', error.error.message);
} else {
// 服务端错误
console.error(`服务端错误 ${error.status}: ${error.error}`);
}
return throwError('发生错误,请重试');
}
9. 状态管理
9.1 服务状态管理
TypeScript
@Injectable({ providedIn: 'root' })
export class UserStore {
private users = new BehaviorSubject<User[]>([]);
private loading = new BehaviorSubject<boolean>(false);
users$ = this.users.asObservable();
loading$ = this.loading.asObservable();
loadUsers() {
this.loading.next(true);
this.userService.getUsers().subscribe(users => {
this.users.next(users);
this.loading.next(false);
});
}
}
9.2 NgRx 状态管理 (可选)
TypeScript
// Action
export const loadUsers = createAction('[User] Load Users');
export const loadUsersSuccess = createAction(
'[User] Load Users Success',
props<{ users: User[] }>()
);
// Reducer
export const userReducer = createReducer(
initialState,
on(loadUsers, state => ({ ...state, loading: true })),
on(loadUsersSuccess, (state, { users }) => ({
...state,
users,
loading: false
}))
);
// Effect
loadUsers$ = createEffect(() => this.actions$.pipe(
ofType(loadUsers),
mergeMap(() => this.userService.getUsers().pipe(
map(users => loadUsersSuccess({ users })),
catchError(() => of(loadUsersFailure()))
))
));
10. 性能优化
10.1 变更检测策略
TypeScript
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
changeDetection: ChangeDetectionStrategy.OnPush // 使用 OnPush 策略
})
export class UserListComponent {
@Input() users: User[];
}
10.2 懒加载
TypeScript
const routes: Routes = [
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
}
];
10.3 跟踪函数
html
<div *ngFor="let user of users; trackBy: trackByUserId">
{{user.name}}
</div>
TypeScript
trackByUserId(index: number, user: User): number {
return user.id;
}
11. 测试
11.1 组件测试
TypeScript
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [UserComponent],
imports: [HttpClientTestingModule],
providers: [UserService]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('应该创建组件', () => {
expect(component).toBeTruthy();
});
it('应该显示用户名称', () => {
component.user = { id: 1, name: '张三' };
fixture.detectChanges();
const compiled = fixture.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('张三');
});
});
12. 高级特性
12.1 动态组件
TypeScript
export class ModalService {
constructor(private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector) {}
createModal(component: Type<any>): ComponentRef<any> {
const factory = this.componentFactoryResolver.resolveComponentFactory(component);
return factory.create(this.injector);
}
}
12.2 自定义指令
TypeScript
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() appHighlight: string;
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.appHighlight || 'yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
12.3 自定义管道
TypeScript
@Pipe({
name: 'reverse'
})
export class ReversePipe implements PipeTransform {
transform(value: string): string {
return value.split('').reverse().join('');
}
}
13. Angular CLI 重要命令
bash
# 创建新项目
ng new my-app
# 生成组件
ng generate component user-list
# 生成服务
ng generate service user
# 生成模块
ng generate module admin
# 构建项目
ng build --prod
# 运行测试
ng test
# 运行端到端测试
ng e2e
14. 总结
Angular 是一个完整的前端框架,具有以下核心特点:
**1)模块化架构:**通过 NgModule 组织代码。
**2)组件化开发:**可复用的 UI 组件。
**3)依赖注入:**强大的服务管理。
**4)TypeScript 支持:**类型安全和更好的开发体验。
**5)强大的工具链:**Angular CLI 提供完整的开发工作流。
**6)丰富的生态系统:**路由、表单、HTTP 等内置功能。
