NGXS状态管理核心概念:State详解
store 🚀 NGXS - State Management for Angular 项目地址: https://gitcode.com/gh_mirrors/sto/store
什么是State
在NGXS状态管理库中,State(状态)是应用数据存储的核心容器。它类似于Redux中的reducer,但采用了更现代化的实现方式,通过装饰器和类来定义状态容器及其行为。
状态定义基础
定义一个状态容器非常简单,只需要创建一个类并使用@State
装饰器:
import { Injectable } from '@angular/core';
import { State } from '@ngxs/store';
@State<string[]>({
name: 'animals',
defaults: []
})
@Injectable()
export class AnimalsState {}
@State
装饰器接收一个配置对象,其中包含三个关键属性:
name
:状态的唯一标识符,必须是有效的对象属性名defaults
:状态的初始值children
(已废弃):子状态关联,新项目不建议使用
状态依赖注入
NGXS状态容器完全支持Angular的依赖注入系统,这使得我们可以在状态类中注入所需的服务:
@State<ZooStateModel>({
name: 'zoo',
defaults: {
feed: false
}
})
@Injectable()
export class ZooState {
constructor(private zooService: ZooService) {}
}
使用StateToken定义状态
为了更好的类型安全和重构能力,NGXS提供了StateToken来替代直接使用字符串名称:
const ZOO_STATE_TOKEN = new StateToken<ZooStateModel>('zoo');
@State({
name: ZOO_STATE_TOKEN,
defaults: {
feed: false
}
})
@Injectable()
export class ZooState {}
这种方式在大型项目中特别有用,可以避免硬编码字符串带来的维护问题。
状态操作:Action处理
状态通过@Action
装饰器来响应各种操作。Action是NGXS中改变状态的唯一方式。
基础Action处理
@Action(FeedAnimals)
feedAnimals(ctx: StateContext<ZooStateModel>) {
const state = ctx.getState();
ctx.setState({
...state,
feed: !state.feed
});
}
StateContext
提供了几个关键方法:
getState()
:获取当前状态(总是返回最新值)setState()
:设置新状态patchState()
:部分更新状态
带参数的Action
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
const state = ctx.getState();
ctx.patchState({
zebraFood: [...state.zebraFood, action.zebraToFeed]
});
}
patchState
是setState
的简化版,特别适合部分状态更新。
状态更新方式对比
NGXS提供了两种状态更新方式:
- 直接提供新状态对象:
ctx.setState({ ...ctx.getState(), value: payload });
- 使用函数返回新状态:
ctx.setState((state) => ({ ...state, value: payload }));
第二种方式更利于使用状态操作符和实现更声明式的代码。
高级状态更新技巧
使用Immer简化不可变更新
import produce from 'immer';
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
ctx.setState(produce((draft) => {
draft.zebraFood.push(action.zebraToFeed);
}));
}
Immer库允许我们以可变的方式编写代码,但实际上执行的是不可变更新。
创建可复用的状态更新函数
function addToZebraFood(itemToAdd) {
return produce((draft) => {
draft.zebraFood.push(itemToAdd);
});
}
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
ctx.setState(addToZebraFood(action.zebraToFeed));
}
这种方式可以大大提高代码的复用性和可维护性。
异步操作处理
NGXS完美支持异步操作,无需额外中间件。
使用Observable
@Action(FeedAnimals)
feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
return this.animalService.feed(action.animalsToFeed).pipe(
tap(animalsToFeedResult => {
ctx.patchState({
feedAnimals: [...ctx.getState().feedAnimals, animalsToFeedResult]
});
})
);
}
使用async/await
@Action(FeedAnimals)
async feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
const result = await this.animalService.feed(action.animalsToFeed);
ctx.patchState({
feedAnimals: [...ctx.getState().feedAnimals, result]
});
}
Action间的级联调用
在一个Action处理完成后,可以继续派发其他Action:
@Action(FeedAnimals)
feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
const state = ctx.getState();
ctx.patchState({
feedAnimals: [...state.feedAnimals, action.animalsToFeed]
});
return ctx.dispatch(new TakeAnimalsOutside());
}
对于异步操作:
@Action(FeedAnimals)
feedAnimals2(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
return this.animalService.feed(action.animalsToFeed).pipe(
tap(result => ctx.patchState({ feedAnimals: result })),
mergeMap(() => ctx.dispatch(new TakeAnimalsOutside()))
);
}
总结
NGXS的State概念提供了一种强大而灵活的方式来管理应用状态。通过类+装饰器的组合,我们能够:
- 清晰地定义状态结构和初始值
- 通过Action响应各种状态变更
- 处理同步和异步操作
- 实现Action间的级联调用
- 使用各种技巧简化不可变更新
这些特性使得NGXS成为Angular应用中状态管理的优秀选择,既保持了Redux的核心思想,又提供了更符合Angular习惯的开发体验。
store 🚀 NGXS - State Management for Angular 项目地址: https://gitcode.com/gh_mirrors/sto/store
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考