Angular statusmanagementoverview
statusmanagement is before 端applicationDevelopmentin important concepts, 它用于managementapplicationin datastatus, 确保data consistency and 可预测性. Angular providing了 many 种statusmanagement方式, including in 置 statusmanagementmechanism and 第三方statusmanagementlibrary.
提示
for 于 simple application, 可以using Angular in 置 statusmanagementmechanism; for 于 complex application, 建议using第三方statusmanagementlibrary, such as NgRx or NgXs.
1. in 置statusmanagement
Angular providing了 many 种 in 置 statusmanagement方式, includingcomponentstatus, servicestatus and 输入输出绑定etc..
1.1 componentstatus
componentstatus is 指store in componentclassin data, 它只 for 当 before component可见:
// counter.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
计数器: {{ count }}
`
})
export class CounterComponent {
count = 0; // componentstatus
increment() {
this.count++;
}
decrement() {
this.count--;
}
}
1.2 servicestatus
servicestatus is 指store in servicein data, 它可以被 many 个component共享:
// user.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
// using BehaviorSubject storestatus
private currentUserSubject = new BehaviorSubject(null);
currentUser$ = this.currentUserSubject.asObservable();
constructor() { }
// updatestatus method
setCurrentUser(user: any) {
this.currentUserSubject.next(user);
}
// 清除status method
clearCurrentUser() {
this.currentUserSubject.next(null);
}
}
// usingservicestatus component
import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';
@Component({
selector: 'app-user-profile',
template: `
欢迎, {{ user.name }}!
请先login
`
})
export class UserProfileComponent implements OnInit {
currentUser$ = this.userService.currentUser$;
constructor(private userService: UserService) { }
ngOnInit(): void {
}
logout() {
this.userService.clearCurrentUser();
}
}
2. NgRx statusmanagement
NgRx is Angular ecosystemin最流行 statusmanagementlibrary之一, 它基于 Redux 模式, providing了强 big statusmanagementfunctions.
2.1 installation NgRx
npm install @ngrx/store @ngrx/effects @ngrx/store-devtools --save
2.2 NgRx core concepts
NgRx 基于以 under core concepts:
- Store: storeapplicationstatus containers
- Action: describesstatus变化 event
- Reducer: 根据 Action updatestatus 纯function
- Effect: processing副作用 (such as HTTP request) mechanism
- Selector: from Store in选择status 纯function
2.3 定义 Action
// counter.actions.ts
import { createAction, props } from '@ngrx/store';
export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
export const reset = createAction('[Counter] Reset');
export const incrementBy = createAction('[Counter] Increment By', props<{ value: number }>());
2.4 定义 Reducer
// counter.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { increment, decrement, reset, incrementBy } from './counter.actions';
export interface CounterState {
count: number;
}
export const initialState: CounterState = {
count: 0
};
export const counterReducer = createReducer(
initialState,
on(increment, state => ({ ...state, count: state.count + 1 })),
on(decrement, state => ({ ...state, count: state.count - 1 })),
on(reset, state => ({ ...state, count: 0 })),
on(incrementBy, (state, { value }) => ({ ...state, count: state.count + value }))
);
2.5 register Store
// app.module.ts
import { StoreModule } from '@ngrx/store';
import { counterReducer } from './counter.reducer';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@NgModule({
imports: [
BrowserModule,
StoreModule.forRoot({ count: counterReducer }), // register根 Store
StoreDevtoolsModule.instrument({ maxAge: 25 }) // 启用 Store DevTools
],
// ...
})
export class AppModule { }
2.6 in componentinusing Store
// counter.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { increment, decrement, reset, incrementBy } from './counter.actions';
import { selectCount } from './counter.selectors';
@Component({
selector: 'app-counter',
template: `
计数器: {{ count$ | async }}
`
})
export class CounterComponent {
count$ = this.store.select(selectCount);
constructor(private store: Store) { }
increment() {
this.store.dispatch(increment());
}
decrement() {
this.store.dispatch(decrement());
}
reset() {
this.store.dispatch(reset());
}
incrementBy(value: number) {
this.store.dispatch(incrementBy({ value }));
}
}
// counter.selectors.ts
import { createSelector } from '@ngrx/store';
import { CounterState } from './counter.reducer';
export const selectCounterState = (state: { count: CounterState }) => state.count;
export const selectCount = createSelector(
selectCounterState,
(state: CounterState) => state.count
);
3. NgXs statusmanagement
NgXs is 另一个流行 Angular statusmanagementlibrary, 它基于statuscontainers模式, providing了更简洁 API.
3.1 installation NgXs
npm install @ngxs/store @ngxs/logger-plugin @ngxs/devtools-plugin --save
3.2 NgXs core concepts
NgXs 基于以 under core concepts:
- State: storeapplicationstatus class
- Action: describesstatus变化 event
- Selector: from State in选择status method
3.3 定义 State
// counter.state.ts
import { State, Action, StateContext } from '@ngxs/store';
import { Increment, Decrement, Reset, IncrementBy } from './counter.actions';
export class CounterStateModel {
count: number;
}
@State({
name: 'counter',
defaults: {
count: 0
}
})
export class CounterState {
@Action(Increment)
increment(ctx: StateContext) {
const state = ctx.getState();
ctx.setState({ count: state.count + 1 });
}
@Action(Decrement)
decrement(ctx: StateContext) {
const state = ctx.getState();
ctx.setState({ count: state.count - 1 });
}
@Action(Reset)
reset(ctx: StateContext) {
ctx.setState({ count: 0 });
}
@Action(IncrementBy)
incrementBy(ctx: StateContext, action: IncrementBy) {
const state = ctx.getState();
ctx.setState({ count: state.count + action.payload.value });
}
}
3.4 定义 Action
// counter.actions.ts
export class Increment {
static readonly type = '[Counter] Increment';
}
export class Decrement {
static readonly type = '[Counter] Decrement';
}
export class Reset {
static readonly type = '[Counter] Reset';
}
export class IncrementBy {
static readonly type = '[Counter] Increment By';
constructor(public payload: { value: number }) { }
}
3.5 register NgXs
// app.module.ts
import { NgxsModule } from '@ngxs/store';
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
import { CounterState } from './counter.state';
@NgModule({
imports: [
BrowserModule,
NgxsModule.forRoot([CounterState]), // register根 State
NgxsLoggerPluginModule.forRoot(), // 启用log插件
NgxsReduxDevtoolsPluginModule.forRoot() // 启用 DevTools 插件
],
// ...
})
export class AppModule { }
3.6 in componentinusing NgXs
// counter.component.ts
import { Component } from '@angular/core';
import { Store, Select } from '@ngxs/store';
import { Increment, Decrement, Reset, IncrementBy } from './counter.actions';
import { CounterState } from './counter.state';
import { Observable } from 'rxjs';
@Component({
selector: 'app-counter',
template: `
计数器: {{ count$ | async }}
`
})
export class CounterComponent {
@Select(CounterState) count$: Observable<{ count: number }>;
constructor(private store: Store) { }
increment() {
this.store.dispatch(new Increment());
}
decrement() {
this.store.dispatch(new Decrement());
}
reset() {
this.store.dispatch(new Reset());
}
incrementBy(value: number) {
this.store.dispatch(new IncrementBy({ value }));
}
}
4. statusmanagementbest practices
- 根据applicationcomplexity选择合适 statusmanagement方式
- 将status集inmanagement, 避免分散 status
- using不可变dataupdatestatus, 确保status 可预测性
- using选择器 from statusin获取data, 避免直接访问status
- 将副作用 (such as HTTP request) and statusupdate分离
- using DevTools debugstatus变化
- for status定义清晰 class型, 确保class型security
- 避免 in statusinstore计算property, using选择器动态计算
5. 选择合适 statusmanagementsolutions
选择statusmanagementsolutions时, 需要考虑以 under 因素:
- application规模: small 型application可以using in 置statusmanagement, big 型application建议using NgRx or NgXs
- 团队experience: such as果团队熟悉 Redux 模式, 可以选择 NgRx; such as果团队喜欢更简洁 API, 可以选择 NgXs
- performance要求: for 于 high performance要求 application, 建议using NgRx or NgXs
- ecosystem: NgRx 拥 has 更丰富 ecosystem, NgXs 则更简洁易用
练习 1: usingservicestatus
- creation一个购物车service, 用于management购物车in 商品
- using BehaviorSubject store购物车status
- implementation添加商品, delete商品, 清空购物车etc.method
- creation两个component, 一个用于显示商品list, 一个用于显示购物车 in 容
- in componentinusing购物车service, implementation添加商品 to 购物车 functions
练习 2: using NgRx
- installation NgRx 及其相关依赖
- creation一个待办事项application statusmanagement
- 定义待办事项 Action, Reducer and Selector
- register Store 并启用 DevTools
- creationcomponent, using Store implementation待办事项 添加, delete and completionfunctions