Angular 基础与进阶
约 1568 字大约 5 分钟
Angular 基础与进阶
Angular核心概念 🟢
1. 组件基础
组件是Angular应用的基本构建块,它由以下几个部分组成:
- 组件装饰器:
- 定义组件的元数据
- 指定模板和样式
- 配置组件的行为
- 设置组件的生命周期
- 组件类:
- 管理组件的数据和行为
- 处理用户交互
- 实现业务逻辑
- 与服务进行交互
代码示例:
// 基础组件示例
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-user-card',
template: `
<div class="user-card" [class.active]="isActive">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
<button (click)="onSelect()">选择</button>
</div>
`,
styles: [`
.user-card {
padding: 16px;
border: 1px solid #ccc;
border-radius: 4px;
}
.user-card.active {
border-color: #007bff;
}
`]
})
export class UserCardComponent implements OnInit {
@Input() user: User;
@Input() isActive = false;
@Output() select = new EventEmitter<User>();
constructor() {}
ngOnInit(): void {
// 组件初始化逻辑
}
onSelect(): void {
this.select.emit(this.user);
}
}
// 使用组件
@Component({
selector: 'app-user-list',
template: `
<div class="user-list">
<app-user-card
*ngFor="let user of users"
[user]="user"
[isActive]="selectedUser?.id === user.id"
(select)="onUserSelect($event)">
</app-user-card>
</div>
`
})
export class UserListComponent {
users: User[] = [];
selectedUser: User | null = null;
onUserSelect(user: User): void {
this.selectedUser = user;
}
}
2. 服务与依赖注入
服务是用于共享数据和功能的可重用类,通过依赖注入系统进行管理:
- 服务定义:
- 使用@Injectable装饰器
- 定义服务的作用域
- 实现共享功能
- 管理状态和数据
- 依赖注入:
- 注入器层级
- 提供者配置
- 服务实例化
- 生命周期管理
代码示例:
// 用户服务
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiUrl = 'api/users';
private users$ = new BehaviorSubject<User[]>([]);
constructor(private http: HttpClient) {
this.loadUsers();
}
// 获取用户列表
getUsers(): Observable<User[]> {
return this.users$.asObservable();
}
// 加载用户数据
private loadUsers(): void {
this.http.get<User[]>(this.apiUrl)
.pipe(
catchError(error => {
console.error('加载用户失败:', error);
return of([]);
})
)
.subscribe(users => this.users$.next(users));
}
// 添加用户
addUser(user: User): Observable<User> {
return this.http.post<User>(this.apiUrl, user)
.pipe(
tap(newUser => {
const currentUsers = this.users$.value;
this.users$.next([...currentUsers, newUser]);
}),
catchError(this.handleError)
);
}
// 更新用户
updateUser(user: User): Observable<User> {
const url = `${this.apiUrl}/${user.id}`;
return this.http.put<User>(url, user)
.pipe(
tap(updatedUser => {
const currentUsers = this.users$.value;
const index = currentUsers.findIndex(u => u.id === user.id);
if (index !== -1) {
currentUsers[index] = updatedUser;
this.users$.next([...currentUsers]);
}
}),
catchError(this.handleError)
);
}
// 删除用户
deleteUser(id: number): Observable<void> {
const url = `${this.apiUrl}/${id}`;
return this.http.delete<void>(url)
.pipe(
tap(() => {
const currentUsers = this.users$.value;
this.users$.next(
currentUsers.filter(user => user.id !== id)
);
}),
catchError(this.handleError)
);
}
// 错误处理
private handleError(error: HttpErrorResponse) {
console.error('API错误:', error);
return throwError(() => new Error('操作失败,请重试'));
}
}
Angular高级特性 🟡
1. 变更检测
Angular的变更检测机制负责更新视图以反映数据的变化:
- 变更检测策略:
- Default: 自动检测所有可能的变化
- OnPush: 仅在输入属性变化时检测
- 手动触发变更检测
- 性能优化考虑
代码示例:
// OnPush策略示例
@Component({
selector: 'app-performance',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div>
<h2>{{ title }}</h2>
<p>{{ message }}</p>
<button (click)="update()">更新</button>
</div>
`
})
export class PerformanceComponent {
@Input() title: string;
message = '初始消息';
constructor(private cd: ChangeDetectorRef) {}
update(): void {
this.message = '更新的消息';
// 手动触发变更检测
this.cd.markForCheck();
}
}
2. 路由与导航
Angular路由系统提供了强大的客户端导航功能:
- 路由配置:
- 路由定义
- 路由参数
- 子路由
- 路由守卫
- 导航功能:
- 命令式导航
- 声明式导航
- 路由事件
- 路由重用策略
代码示例:
// 路由配置
const routes: Routes = [
{
path: 'users',
component: UserListComponent,
canActivate: [AuthGuard],
children: [
{
path: ':id',
component: UserDetailComponent,
resolve: {
user: UserResolver
}
}
]
},
{
path: 'admin',
loadChildren: () => import('./admin/admin.module')
.then(m => m.AdminModule),
canLoad: [AdminGuard]
}
];
// 路由守卫
@Injectable({ providedIn: 'root' })
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthService,
private router: Router
) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): boolean | UrlTree {
if (this.authService.isAuthenticated()) {
return true;
}
return this.router.createUrlTree(['/login'], {
queryParams: { returnUrl: state.url }
});
}
}
// 路由复用策略
@Injectable()
export class CustomRouteReuseStrategy implements RouteReuseStrategy {
private storedRoutes = new Map<string, DetachedRouteHandle>();
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return route.data['reuse'] === true;
}
store(
route: ActivatedRouteSnapshot,
handle: DetachedRouteHandle
): void {
const id = this.getRouteId(route);
this.storedRoutes.set(id, handle);
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
const id = this.getRouteId(route);
return this.storedRoutes.has(id);
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
const id = this.getRouteId(route);
return this.storedRoutes.get(id) || null;
}
shouldReuseRoute(
future: ActivatedRouteSnapshot,
curr: ActivatedRouteSnapshot
): boolean {
return future.routeConfig === curr.routeConfig;
}
private getRouteId(route: ActivatedRouteSnapshot): string {
return route.routeConfig?.path || '';
}
}
3. 表单处理
Angular提供了两种表单处理方式:模板驱动表单和响应式表单:
- 响应式表单:
- FormGroup和FormControl
- 表单验证
- 动态表单
- 自定义验证器
代码示例:
// 响应式表单示例
@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="form-control"
[class.is-invalid]="nameControl.invalid && nameControl.touched"
>
<div class="invalid-feedback" *ngIf="nameControl.errors?.['required']">
姓名是必填项
</div>
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input
id="email"
type="email"
formControlName="email"
class="form-control"
[class.is-invalid]="emailControl.invalid && emailControl.touched"
>
<div class="invalid-feedback" *ngIf="emailControl.errors?.['email']">
请输入有效的邮箱地址
</div>
</div>
<div formGroupName="address">
<div class="form-group">
<label for="street">街道</label>
<input
id="street"
type="text"
formControlName="street"
class="form-control"
>
</div>
<div class="form-group">
<label for="city">城市</label>
<input
id="city"
type="text"
formControlName="city"
class="form-control"
>
</div>
</div>
<button
type="submit"
class="btn btn-primary"
[disabled]="userForm.invalid"
>
提交
</button>
</form>
`
})
export class UserFormComponent implements OnInit {
userForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit(): void {
this.userForm = this.fb.group({
name: ['', [Validators.required, Validators.minLength(2)]],
email: ['', [Validators.required, Validators.email]],
address: this.fb.group({
street: [''],
city: ['']
})
});
// 表单值变化监听
this.userForm.valueChanges
.pipe(
debounceTime(500),
distinctUntilChanged()
)
.subscribe(value => {
console.log('表单值变化:', value);
});
}
get nameControl() {
return this.userForm.get('name');
}
get emailControl() {
return this.userForm.get('email');
}
onSubmit(): void {
if (this.userForm.valid) {
console.log('表单提交:', this.userForm.value);
}
}
}
4. 状态管理
Angular应用中的状态管理可以使用NgRx等库:
- Store概念:
- Actions: 描述状态变更的意图
- Reducers: 处理状态变更的纯函数
- Selectors: 获取状态的函数
- Effects: 处理副作用
代码示例:
// 状态管理示例
// actions.ts
export const loadUsers = createAction('[User] Load Users');
export const loadUsersSuccess = createAction(
'[User] Load Users Success',
props<{ users: User[] }>()
);
export const loadUsersFailure = createAction(
'[User] Load Users Failure',
props<{ error: any }>()
);
// reducer.ts
export interface UserState {
users: User[];
loading: boolean;
error: any;
}
const initialState: UserState = {
users: [],
loading: false,
error: null
};
export const userReducer = createReducer(
initialState,
on(loadUsers, state => ({
...state,
loading: true
})),
on(loadUsersSuccess, (state, { users }) => ({
...state,
loading: false,
users
})),
on(loadUsersFailure, (state, { error }) => ({
...state,
loading: false,
error
}))
);
// effects.ts
@Injectable()
export class UserEffects {
loadUsers$ = createEffect(() =>
this.actions$.pipe(
ofType(loadUsers),
mergeMap(() => this.userService.getUsers()
.pipe(
map(users => loadUsersSuccess({ users })),
catchError(error => of(loadUsersFailure({ error })))
))
)
);
constructor(
private actions$: Actions,
private userService: UserService
) {}
}
// selectors.ts
export const selectUserState = createFeatureSelector<UserState>('user');
export const selectAllUsers = createSelector(
selectUserState,
state => state.users
);
export const selectUserLoading = createSelector(
selectUserState,
state => state.loading
);
export const selectUserError = createSelector(
selectUserState,
state => state.error
);
// component.ts
@Component({
selector: 'app-user-list',
template: `
<div *ngIf="loading$ | async">加载中...</div>
<div *ngIf="error$ | async as error">
加载失败: {{ error }}
</div>
<ul *ngIf="users$ | async as users">
<li *ngFor="let user of users">
{{ user.name }}
</li>
</ul>
`
})
export class UserListComponent implements OnInit {
users$ = this.store.select(selectAllUsers);
loading$ = this.store.select(selectUserLoading);
error$ = this.store.select(selectUserError);
constructor(private store: Store) {}
ngOnInit(): void {
this.store.dispatch(loadUsers());
}
}
通过以上内容,我们详细介绍了Angular的各个方面,包括:
- 组件和服务的基础概念
- 变更检测和性能优化
- 路由系统的高级特性
- 表单处理和验证
- 状态管理的实现
这些内容可以帮助开发者更好地理解和使用Angular框架。