首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

NgRx 10引入组件本地状态管理包

NgRx,一个基于RxJS的Angular反应式扩展平台,发布了它的第10个主要迭代版本,包含了一个用于本地状态管理的新组件存储包。新包对用于应用程序状态管理的NgRx存储进行了扩展。此外,一个新的实验性NgRx组件包为开发人员开发Angular无分区应用程序提供支持,它利用了Angular Ivy的能力,以此来获得更好的性能。

Brandon Roberts在NgRx的发布说明中解释了新的本地组件存储所带来的价值:

NgRx Store用于在全局应用程序级别管理来自多个不同来源的复杂状态。在某些情况下,用户希望以统一的方式在本地管理状态,不需要间接的操作、reducer和effects。我们设计了一个新的包来处理本地级别的状态,同时提供与NgRx Store类似的好处。

NgRx应用程序的架构围绕着四个关键概念,这些概念让人联想到Redux或Elm的架构。动作会捕获事件,无论事件是来自用户或来自其他接口系统(例如套接字或REST服务器):

import { createAction, props } from '@ngrx/store';
export const login = createAction(
  '[Login Page] Login',
  props<{ username: string; password: string }>()
); 

事件处理器通常分派用户触发的动作 (即上述代码示例中的 login):

onSubmit(username: string, password: string) {
  store.dispatch(login({ username: username, password: password }));
}

应用程序级别的 NgRx Store 通过更新其内容 (即应用程序级别的状态) 或调度 NgRx effects 来处理分派的操作。这种行为与反应式系统的基本方程是一致的。

顶层状态容器可以帮助开发人员创建可维护的显式应用程序,所有的状态更新都可以追溯到触发事件。这实际上是 Redux 的 promise。

然而,在很多情况下,特别是在具有大量小组件且作用域很小的应用程序中,开发人员使用的组件是读取和更新特定状态的唯一组件。这些状态通常与特定组件的生命周期相关联,并且在组件被销毁时失效。因此,新的 NgRx 组件存储允许开发人员创建在本地处理这些状态片段的组件——本地状态。

发布说明里写道:

ComponentStore 是一个独立的用于管理本地 / 组件状态的库,是响应式推送的替代方法。

组件存储可以在定义存储时直接初始化:

export interface MoviesState {
  movies: Movie[];
}
@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {
  constructor() {
    super({movies: []});
  }
}

组件存储也可以在创建组件时使用 setState 方法来初始化:

@Component({
  template: `
    <li *ngFor="let movie of (movies$ | async)">
      {{ movie.name }}
    </li>
  `,
  providers: [ComponentStore],
})
export class MoviesPageComponent {
  readonly movies$ = this.componentStore.state$.pipe(
    map(state => state.movies),
  );
  constructor(
    private readonly componentStore: ComponentStore<{movies: Movie[]}>
  ) {}
  ngOnInit() {
    this.componentStore.setState({movies: []});
  }
}

组件存储提供了 select 和 updater 方法来读取本地状态,类似于功能透镜。setState 方法用来更新和替换整个本地状态。最后,effect 方法可以在可观察的管道内运行 effects:

@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {
  constructor(private readonly moviesService: MoviesService) {
    super({movies: []});
  }
  // 每次调用 getMovie(id) 都会将当前 ID 推送到 movieId$ 流中。
  readonly getMovie = this.effect((movieId$: Observable<string>) => {
    return movieId$.pipe(
      // 处理竞态条件。
      switchMap((id) => this.moviesService.fetchMovie(id).pipe(
        // 在内部管道处理结果。
        tap({
          next: (movie) => this.addMovie(movie),
          error: (e) => this.logError(e),
        }),
        //  在内部管道处理潜在的错误。
        catchError(() => EMPTY),
      ))
    );
  })
  readonly addMovie = this.updater((state, movie: Movie) => ({
    movies: [...state.movies, movie],
  }));
  selectMovie(movieId: string) {
    return this.select((state) => state.movies.find(m => m.id === movieId));
  }
}

可以通过 npm 来安装新的组件存储:

npm install @ngrx/component-store --save

或者使用 Angular CLI 来安装:

ng add @ngrx/component-store@latest

NgRx 10 还提供了一个实验性的 NgRx 组件包。发布说明里写道:

随着 Ivy 的不断发展,我们需要重新思考如何处理 Angular 无分区应用程序中的反应式。async 管道为 Angular 应用程序处理模板中的可观察对象和 promise 设置了一个标准。NgRx 组件进一步帮你构建完全反应式的应用程序,帮你使用模板中的可观察对象进行渲染。NgRx 组件让我们看到了构建反应式 Angular 应用程序的新方法。

实验包提供了两个指令ngrxLet 和ngrxPush,文档中分别对它们进行了解释。

Angular 无分区应用程序在处理变化检测时无需依赖 Angular 无分区机制,这样可能会提高运行时性能。Angular Ivy 和提前编译为此提供了新的可能性。

NgRx 采用了 MIT 许可。欢迎开发者参与贡献,并请遵循贡献指南。

原文链接

Reactive Angular Library NgRx v10 Adds Component Local State Management Package

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/5tLhmOXDvi7H1PfGdiIg
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券