NgRx 是一个用于 Angular 应用开发的响应式 State 管理工具库。
受到 Redux 的影响,Ngrx 底层使用 Rxjs 来允许用户管理整个应用的全局状态。
不是每个应用程序都需要状态管理解决方案,但是集中应用程序的状态和逻辑可以实现撤消/重做、状态持久性等强大功能。
使用NgRx需要理解一些关键概念,Actions 就是其中之一。
在NgRx上下文中,动作描述的是可以从任何地方(例如组件和服务)分派的唯一事件实例。
下面的代码展示了一个简单操作的样子。显示登录屏幕的组件可以调度(dispatch)这个动作,告诉正在监听的人(例如 effect )应该发送一个到后端登录 endpoint 的HTTP请求。登录数据通过调度 action 提供:
通过 @ngrx/store
的 createAction
构造器创建了一个 Action 实例,包含了用户输入的用户名和密码。
对于上图所示的源代码,可以编写单元测试代码,检查提交了 login form 之后,是否调度了对应的 action.
如果应用程序变大,应用程序状态也会变大。一开始你可能只有几个动作,一个减速器和两个效果,但几年后,你可能突然有动作、减速器和效果分散在不同团队的不同应用程序和库中。
本文我们一起来探讨一种简易的通过 ActionSubject 实现的探测某 Action 是否已经 Dispatch 的方式。
NgRx提供了一个整洁的实用程序ActionsSubject,我们可以通过依赖注入来访问它,如下图所示:
这个名字已经表明我们在使用 Subject
的概念了。Subject 是 Observable 的一种特殊类型。因此,我们可以订阅它以获得它的最新值。在本例中,我们通过该流检索的任何值都是一个已分派的NgRx Action。
通过订阅ActionsSubject,我们将收到应用程序中任何正在分派的操作的通知。我们可以记录传入的操作,以验证是否使用正确的数据和正确的顺序分派了适当的操作。这有助于理解在整个会话中如何以及何时分派操作。
代码如下图所示:
import { Component, OnInit } from '@angular/core';
import { ActionsSubject } from '@ngrx/store';
import { skip } from 'rxjs/operators';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private actionListener$: ActionsSubject) {}
ngOnInit() {
this.actionListener$.pipe(
skip(1) // optional: skips initial logging done by ngrx
).subscribe((action) => console.info('ngrx action', action));
}
}
上述代码的几处关键点:
- 添加了
skip(1)
来避免记录NgRx自己调度的第一个操作。 - 开发人员应该考虑是否真的想要记录任何分派操作。毕竟,您可能不希望在生产环境中记录用户凭据。一种方法是在开发模式下只侦听,从而在生产环境中禁用任何操作日志记录。
- 应该取消订阅以避免内存泄漏。例如,可以在Angular提供的ngOnDestroy生命周期钩子中保留订阅和取消订阅的引用。
在较大的应用程序中,这种方法可以通过记录任何已分派的操作来真正帮助我们理解何时以及如何分派操作。幸运的是,NgRx让我们很容易做到这一点。不需要另一个包或浏览器扩展。