随着前端应用的不断复杂化,状态管理在我们的开发过程中变得越来越重要。而 NgRx 是一个非常流行的状态管理库,它允许我们以一种统一的方式来管理应用程序中的数据,并提供了一套强大的工具来管理应用程序的状态。
本文将向您介绍如何在 Angular 应用中使用 NgRx 进行状态管理的最佳实践,如何在最优化的方式下使用 NgRx 并提供实例代码。
NgRx 简介
NgRx 是一个基于 Redux 架构的状态管理库,在 Angular 应用中非常流行。它允许我们使用 RxJS 来监听和响应应用程序中的状态变化,并且遵循一些开发最佳实践来创建一个稳健和高效的状态管理系统。
使用 NgRx 可以让我们更容易地管理应用程序中的状态,并且提供了一些额外的优点:
- 状态的所有变化都被记录下来,可以更容易地追踪特定问题;
- 先进的 RxJS 特性使我们可以更便捷地进行状态查询、权值查找和对错误进行处理;
- 标准化状态管理框架有助于整个开发团队之间的一致性理解和代码可读性;
以上这些优点使得 NgRx 成为一个非常适合 Angular 应用的状态管理库。
NgRx 的核心概念
在深入 NgRx 的最佳实践之前,我们可以先了解一下 NgRx 的核心概念:
Actions
Action 是一个要求对应用程序状态进行修改的普通对象。它们带有一个类型和一个负载,可以使用 .dispatch() 方法来发送。在 NgRx 中,将 Action 作为状态修改的唯一来源,方便我们进行预期的状态跟踪和错误处理。
Reducers
Reducers 是根据 Action 对象中的负载处理应用程序的状态变化的函数。 在 NgRx 应用程序中,我们可以创建多个 Reducer,每个 Reducer 负责管理应用程序的不同部分。Reducers 必须是纯函数,接收当前状态和 Action 对象作为参数并返回新状态。
Store
Store 可以理解为状态容器,它提供了一个基于相关 Reducer 函数对状态进行操作的中心化接口。应用程序中的状态仅存储在 Store 中,通过应用程序的访问 Store 中的状态来更新应用程序。
Effects
Effects 允许我们处理引起状态变化的异步操作。 例如,异步网络请求可以使用 Effects 处理数据获取和响应。Effects 在管道中使用过程中和 Action 相互作用,从而保证一致性和非阻塞操作。
Selectors
Selector 是一个纯函数,用于从 Store 中选择特定部分的状态,以供给视图或组件使用。Selectors 提供了一种从 Store 中获取数据的方法,以避免直接访问 Store。同时,Selectors 还可用于执行复杂的状态处理,例如 Calculate、Filter 和排序。
NgRx 最佳实践
在掌握了 NgRx 的核心概念之后,我们来了解下 NgRx 在 Angular 应用中的最佳实践。
划分职责
应用中的状态可以划分为多种用途,例如支付、用户信息、导航状态等。通常情况下,我们为特定部分的状态创建一个单独的 State 对象,并使用一个 Reducer 函数来处理它。这种拆分的做法更易于维护和扩展,同时也更容易实现类型安全和良好的测试覆盖率。
例如,假设我们的应用需要管理两个状态部分,一个是用户信息,一个是购物车。
-- -------------------- ---- ------- ------ --------- --------- - --------- ------- ---------- ------- --------- ------- - ------ --------- -------- - ---------- ------- ------------ ------- ------ ------- --------- ------- - ------ --------- --------- - ------ ----------- ------ ------- -
使用 Action Creator
Action Creator 是一个辅助函数,它用于创建 Action 对象以及附带将用于状态修改的值的负载。 它们使我们可以避免手动编写状态修改所需的重复代码,并简化了应用程序中 Action 类型的管理。
比如,我们为购物车添加一个商品我们就可以使用 Action Creator 来实现:
-- -------------------- ---- ------- ------------- ------ ----- ----------- - ------ ----------- - ------- --- -- ------ ------------------ ---------- ------ - ------ - ----- ------------------------ ------- -------- -- - -
使用命名约定
Action 类型名称和 Action Creator 名称应该使用特定的命名约定。这将有助于更好地组织我们的代码,并使代码更易读。常见的命名约定包括:
- Actions 的类型名称以方括号 [] 表示,并且包含项目名称和动作名称。
- Action Creators 的名称应与类型名称类似,但是使用驼峰符号。
例如:
export class UserActions { static LOAD_USERS = '[Users] Load Users'; loadUsers(): Action { return { type: UserActions.LOAD_USERS }; } }
处理异步操作
在 Angular 应用中,异步操作是经常遇到的情况,例如获取数据从后端服务器。 NgRx 提供了一些可以用于处理异步操作的工具。我们可以使用 Effect 来处理应用程序中的异步数据获取,Effects 可以帮助我们更容易地跟踪和处理结果。
下面是一个获取用户信息的例子:
-- -------------------- ---- ------- ------------- ------ ----- ----------- - ------------------- ------------ ------------ ------- -------- -------- - - --------- ---------- - ------------------ ------------------------------- ------------------ ---- -- ----------------------------- --------- -- --- ------------------------------------- ---------------- -- ------ ---------------------------------- -- -
管理数据的可变性
在 NgRx 应用中,应该尽可能地保持状态不可变性,这将使我们更容易跟踪和记录状态的变化。 NgRx 推荐的方式是使用聚合器,即 Observable 上的各种操作符来管理状态的可变性,并确保对原有数据做出的修改不会对原始数据本身产生影响。
例如,创建一个新的购物车状态并添加一项商品:
-- -------------------- ---- ------- -------- ------------------ ---------- ------- ------- - ------ ------------- - ---- ------------------------ ----- ------- - --------------- ----- ------------ - ---------------------------- ----- ------------ - ----------- - ------------- - ----------------- ------ - ------ ------------- ------ ------------ -- - -
使用 NgRx DevTools
NgRx DevTools 是一个插件,可以帮助我们更有效地调试应用程序中的状态变化。它提供了一个类似 Redux DevTools 的工具集,包括对状态快照的调试支持、Action 日志等等。
我们只需要在应用程序的 Store 上注册这个插件即可:
-- -------------------- ---- ------- ------------------------------- - -------------- - ------------------------ ----- ------------------------- ----- --------------------------- ----- ---------------------------- ---- - --- --------------------------------
示例代码
下面是一个简单的示例:
https://stackblitz.com/edit/angular-c6jyfy
总结
在本文中,我们了解了 NgRx 应用程序状态管理的核心概念,以及在 Angular 应用程序中使用的最佳实践。遵循这些最佳实践可以帮助我们更好地管理应用程序的状态,提高应用程序的可靠性和可维护性。了解了这些实践后,现在您应该能够为您的应用程序设计一个有效的状态管理系统了。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64ae660c48841e9894a6fe01