Angular statusmanagement

Master Angular statusmanagement, including in 置statusmanagement and 第三方statusmanagementlibrary

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

  1. 根据applicationcomplexity选择合适 statusmanagement方式
  2. 将status集inmanagement, 避免分散 status
  3. using不可变dataupdatestatus, 确保status 可预测性
  4. using选择器 from statusin获取data, 避免直接访问status
  5. 将副作用 (such as HTTP request) and statusupdate分离
  6. using DevTools debugstatus变化
  7. for status定义清晰 class型, 确保class型security
  8. 避免 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

  1. creation一个购物车service, 用于management购物车in 商品
  2. using BehaviorSubject store购物车status
  3. implementation添加商品, delete商品, 清空购物车etc.method
  4. creation两个component, 一个用于显示商品list, 一个用于显示购物车 in 容
  5. in componentinusing购物车service, implementation添加商品 to 购物车 functions

练习 2: using NgRx

  1. installation NgRx 及其相关依赖
  2. creation一个待办事项application statusmanagement
  3. 定义待办事项 Action, Reducer and Selector
  4. register Store 并启用 DevTools
  5. creationcomponent, using Store implementation待办事项 添加, delete and completionfunctions