NGXS状态管理:深入理解Selector选择器机制
store 🚀 NGXS - State Management for Angular 项目地址: https://gitcode.com/gh_mirrors/sto/store
什么是Selector选择器
在NGXS状态管理库中,Selector(选择器)是一种从全局状态容器中提取特定状态片段的函数。它遵循CQRS(命令查询职责分离)和Redux模式,将读取(READ)和写入(WRITE)操作明确分离。
选择器在NGXS中扮演着重要角色,它不仅是状态访问的入口,还能通过多种方式优化状态查询性能。
基础选择器使用
Store服务的选择方法
NGXS的Store
服务提供了多种选择状态的方式:
import { Store } from '@ngxs/store';
@Component({...})
export class ZooComponent {
animals$ = this.store.select(ZooState.getAnimals);
constructor(private store: Store) {}
}
这里select
方法返回一个Observable,当状态变化时会自动推送新值。
一次性选择器
对于只需要当前状态值而不需要持续观察的场景,可以使用selectOnce
:
const currentAnimals = this.store.selectOnce(ZooState.getAnimals);
这在路由守卫或单元测试中特别有用,因为它会自动完成select().pipe(take(1))
的操作。
信号(Signal)选择器
Angular的信号机制也被整合到NGXS中:
@Component({
template: `
@for (panda of pandas(); track $index) {
<p>{{ panda }}</p>
}
`
})
export class ZooComponent {
pandas = this.store.selectSignal(ZooState.getPandas);
constructor(private store: Store) {}
}
selectSignal
方法返回一个Signal,相比Observable更适合在模板中使用。需要注意的是,它只接受类型化的选择器函数,不支持匿名函数。
状态快照选择
有时我们需要直接获取状态的当前值而非响应式流:
@Injectable()
export class JWTInterceptor implements HttpInterceptor {
constructor(private store: Store) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const token = this.store.selectSnapshot<string>(AuthState.getToken);
// 使用token...
}
}
selectSnapshot
直接返回状态的当前值,适合在拦截器等非响应式场景使用。
记忆化选择器
记忆化(Memoization)是选择器的重要特性,它可以缓存计算结果,避免不必要的重复计算:
@State<string[]>({
name: 'animals',
defaults: []
})
@Injectable()
export class ZooState {
@Selector()
static getPandas(state: string[]) {
return state.filter(s => s.includes('panda'));
}
}
使用@Selector
装饰器会自动记忆化函数,并且自动切片处理的状态部分。
选择器选项配置
选择器行为可以通过selectorOptions
全局配置或@SelectorOptions
装饰器局部配置:
suppressErrors
:控制是否抑制选择器中的错误injectContainerState
:控制是否注入容器状态(主要用于迁移)
带参数的选择器
惰性选择器(Lazy Selectors)
返回一个函数的记忆化选择器:
@Selector()
static getPandas(state: string[]) {
return (type: string) => {
return state.filter(s => s.includes('panda') && s.includes(type));
};
}
使用时通过计算信号来获取结果:
babyPandas = computed(() => {
const filterFn = this.pandas();
return filterFn('baby');
});
动态选择器(Dynamic Selectors)
使用createSelector
函数创建:
static getPandas(type: string) {
return createSelector([ZooState], (state: string[]) => {
return state.filter(s => s.includes('panda') && s.includes(type));
});
}
每个参数组合都会创建独立的记忆化实例:
babyPandas = this.store.selectSignal(ZooState.getPandas('baby'));
高级选择器模式
选择器组合
可以将多个选择器组合使用:
@Selector([ZooState, PreferencesState])
static getFirstLocalPanda(state: string[], prefs: PreferencesStateModel) {
return state.find(s => s.includes('panda') && s.includes(prefs.location));
}
元选择器(Meta Selectors)
跨状态组合的选择器:
@Selector([Zoo, ThemePark])
static getZooThemeParks(zoos, themeParks) {
return [...zoos, ...themeParks];
}
选择器继承
通过基类共享选择器逻辑:
export class EntitiesState {
static getEntities<T>() {
return createSelector([this], (state: { entities: T[] }) => state.entities);
}
}
@State<UsersStateModel>(...)
@Injectable()
export class UsersState extends EntitiesState {...}
最佳实践
- 优先使用记忆化选择器提高性能
- 在组件模板中使用
selectSignal
而非Observable - 将复杂选择器逻辑提取到状态类中
- 使用选择器组合避免重复逻辑
- 对于共享数据结构,考虑使用选择器继承
NGXS的选择器机制提供了强大而灵活的状态访问方式,合理使用可以显著提升应用性能和代码可维护性。
store 🚀 NGXS - State Management for Angular 项目地址: https://gitcode.com/gh_mirrors/sto/store
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考