发布于 2026-01-06 0 阅读
0

在 Angular 中选择用于渐进式响应式的状态管理库

在 Angular 中选择用于渐进式响应式的状态管理库

终于到了选择状态管理库的时候了。我用每个状态管理库都实现了我的颜色应用,看看哪个库最能支持本系列文章中描述的“渐进式响应式”模式。

我们将使用以下 3 个标准:

我针对每个库的实现方式都略有不同。例如,NGXS 支持许多常用的命令式编程模式,但我一个也没用。我还创建了一些实用工具,以尽可能地为每个库编写响应式代码。我将在本系列的最后三篇文章中详细讨论这些内容,这些文章很快就会发布。

首先,我们来看结果。

结果(命令式代码)

以下是我的颜色应用程序中,每个状态管理库在最高复杂度级别下所需的最少命令语句数量:

图书馆 祈使句计数 使用响应式工具进行命令式语句计数
NGXS 11 7
NgRx/商店 7 7
秋田 10 4
精灵 10 4
NgRx/组件商店 10 4
服务中的主题 10 4
RxAngular 5 4
状态适应 4 4

Angular 中最少允许使用 4 条命令式语句。不出所料,StateAdapt 实现了最大程度的响应式,因为它正是为此目的而设计的。

RxAngular 是开箱即用的响应式框架中响应速度第二快的,拥有 5 个响应速度。这并不奇怪,因为它是由Michael "Rx" Hladky创建的。

但是标准的 NgRx/store 也非常注重响应式设计,只有 7 条命令式语句。这是为什么呢?而其他版本的响应式设计为什么就没那么强呢?

NgRx/Store 的灵感来源于 Redux,而 Redux 的灵感又来源于 Flux。这和响应式编程或声明式代码有什么关系呢?以下摘自8 年前向世界介绍 Flux 的演示文稿:

“我们有一个外部处理程序,它会介入并修改部分组件的状态。每个组件都有自己的状态,但事件处理程序会修改这些状态​​。所有基于新事件修改状态的逻辑都位于处理程序本身。因此,这三个组件不再能够维护内部一致性。它们基本上没有这些信息。它们已经将控制权交给了处理程序。我们想要做的是将这种控制权内部化。我们希望将所有控制权移到各个组件中,以便状态与更新状态的逻辑紧密相连。

这正是对声明式编程的描述(参见规则 1)。他们称之为“单向数据流”和“单一数据源”,但这些只是“响应式”和“声明式”的另一种说法。所有这些状态管理混乱——所有这些库,所有的一切——都源于编写声明式异步代码的尝试。

对 Flux、Redux 和 NgRx 的负面反应主要有两种:一是抵制大量的样板代码(actions、dispatcher、reducers、“thunk”等);二是抵制反应式本身。

当时 RxJS 还不流行,所以很难责怪 Flux 的语法不如 RxJS 简洁。但人们对冗长语法的抵触情绪是可以理解的:它耗时更长,会掩盖业务逻辑,而且重构起来极其困难。

对被动思考的抵触源于经验不足。无论前端开发人员的编程经验是1年还是10年,只有经历过因脱离上下文的命令式更新而导致复杂性激增,进而造成进展缓慢的痛苦,才能真正体会到声明式代码带来的清晰思路。

结果(代码行数)

以下是我的颜色应用程序中每个状态管理库在不同复杂程度下的代码总行数:

Angular 中 8 种状态管理模式的代码量

然而,在为每个库创建响应式实用程序后,我能够将每个库的代码行数减少 10-20%:

使用响应式实用程序在 Angular 中实现 8 种状态管理模式的代码行数

StateAdapt 保持不变,因为它已经过优化,具有最小性和响应性。

服务中的主题(RxJS)仍然存在,只是位于 NgRx/Component-Store 之下。事实证明,对于这些使用响应式工具的模式,store 和组件类的代码是完全相同的。

这里有个有趣的发现:StateAdapt 的代码量不到 NGXS 的一半。如果你已经在 NGXS 中实现了 Level 3 的复杂度,那么为了适应 Level 4 的复杂度(状态逻辑重用),所需的代码量会非常大,以至于还不如直接删除所有代码,然后在 StateAdapt 中重写 Level 4 的部分。当然,这只是一个极端的例子,其中的业务逻辑极其精简,虽然有利于说明和比较状态管理模式本身,但可能并不反映大多数实际项目的实际情况。

结果(受欢迎程度)

图书馆 每周下载量 GitHub 星标
NgRx/商店 486k 3.9k
NGXS 118k 3.3k
服务中的主题 不适用 不适用
NgRx/组件商店 8万
秋田 42k 3.5k
RxAngular 37k 1.3k
精灵 7.8k 1千
状态适应 139 25

StateAdapt 目前还处于开发初期,不建议在生产环境中使用。不过,1.0 版本应该会在几个月内发布。欢迎大家给它点个赞 :) StateAdapt

那么,选哪一个?

遗憾的是,每个图书馆都有一些问题!

我创建StateAdapt 的初衷是使其成为渐进式响应式开发的完美解决方案,但它尚未准备好用于生产环境。在撰写本文之前,我无法将其准备好用于生产环境,因为我参考了本系列文章来设计语法。

NgRx/Store 是最稳妥的选择,但它的代码行数排名第二,这意味着它的语法不够灵活——如果你一开始选择了一个更简单的方案,但之后为了应对业务需求的变化,功能不得不变得更加复杂,你该怎么办?拖延下去,最终留下更大的烂摊子,同时避免全面切换到 NgRx 吗?如果最终还是需要切换到 NgRx/Store,那么所有方案在语法上都将陷入僵局,因为需要重写和添加的代码量巨大。

NGXS 与之类似,但代码行数更多。它还支持许多命令式编程模式,因此,如果您使用它并希望遵循“渐进式响应式”理念,请确保您的团队非常理解第一条规则。

对于 NgRx/Store 和 NGXS,我的建议是,只有当你的应用非常复杂,并且计划在所有可能变得足够复杂到需要使用选择器和 Redux Devtools 的功能中都用到它们时才使用。对于那些肯定不会变得那么复杂的功能,你可以选择其他四个流行的库。但几乎不可能 100% 确定某个功能永远不会变得更复杂。

服务中的主题、NgRx/Component-Store、Akita、Elf 和 RxAngular 都不支持选择器,而且 Akita 和 Elf 对 Redux Devtools 的支持也相当薄弱(它们只显示 action 类型,不显示 payload/参数)。此外,Akita 和 Elf 的受欢迎程度不如其他框架(StateAdapt 除外)。顺便一提,它们是由同一个人创建的,虽然Akita 目前仍在维护中,但他出于诸多原因更倾向于 Elf。

所以,我也不知道。我真希望我能给你答案。当初开始写这篇文章,深入研究每个状态管理库的时候,我完全没想到会得出这样的结论。但每个库/模式都存在很大的问题,包括 StateAdapt(它还是 1.0 版本之前的,并不流行)。

但我希望帮助所有使用任何状态管理库的 Angular 开发者,因此在接下来的文章中,我将分享如何让每种状态管理模式更加简洁和响应式。我非常希望看到这些方法被库本身采纳,但在采取任何行动之前,我们先看看大家的反馈如何。

我的推荐

我想我得提建议,所以,我的建议是:

  • 对于任何表现出复杂度增加迹象的功能,我将在下一篇文章中解释如何使用 NgRx/Store 以及响应式实用程序。
  • 使用 Angular 的特性,其他所有事情都使用 RxAngular,因为 RxAngular 相当流行,本身就具有很强的响应式特性,并且提供了许多响应式工具。
  • 请在我的一个副项目中使用 StateAdapt,帮助我尽快将其发布到 1.0 版本,这样我们最终就能拥有一个完全支持响应式、选择器和开发者工具的状态管理库,并且其自适应语法无需大量的初始投入。如果您发现任何 bug,请提交 issue。

或者,如果您已经在使用状态管理库,可以采用我在后续文章中介绍的响应式工具,这样您的语法就能与其他库尽可能地保持一致。如果您需要切换状态管理库,这将使您更容易进行横向迁移。例如,如果您正在使用 Akita,您可以采用这些响应式工具,最终得到的代码将与其他基于类的状态管理解决方案极其相似。它也比标准的 Akita 更接近 StateAdapt,因此,当 StateAdapt 更加稳定时,您可以更轻松地切换到它。

如果你对任何假设都判断错误(这种情况肯定会发生),你对此也无能为力——要么你只能接受目标过高而导致的过多样板代码,要么你只能接受原本不透明、混乱不堪的 RxJS 代码(它原本就不是用来处理复杂同步状态的),如果你低估了复杂性的话。

结论

最终,渐进式响应式对您来说有多重要,取决于您自己的判断。我已经尽力说服您,它能创建更简洁的代码,并避免陷入语法死胡同。无论如何,我希望我阐述这些概念的方式能帮助您理解并做出适合您项目的决策。请思考我在本文中提出的结果,并告诉我您的想法。接下来的三篇文章中,我将详细介绍每个库,并提供每个库的 StackBlitz 链接。

文章来源:https://dev.to/this-is-angular/choosing-a-state-management-library-for-progressive-reactivity-in-angular-19j8