NGXS状态管理:深入理解Selector选择器机制

NGXS状态管理:深入理解Selector选择器机制

store 🚀 NGXS - State Management for Angular store 项目地址: 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 {...}

最佳实践

  1. 优先使用记忆化选择器提高性能
  2. 在组件模板中使用selectSignal而非Observable
  3. 将复杂选择器逻辑提取到状态类中
  4. 使用选择器组合避免重复逻辑
  5. 对于共享数据结构,考虑使用选择器继承

NGXS的选择器机制提供了强大而灵活的状态访问方式,合理使用可以显著提升应用性能和代码可维护性。

store 🚀 NGXS - State Management for Angular store 项目地址: https://gitcode.com/gh_mirrors/sto/store

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邵金庆Peaceful

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值