【问题标题】:What are benefits of using store (ngrx) in angular 2在 Angular 2 中使用 store (ngrx) 有什么好处
【发布时间】:2016-05-31 08:08:20
【问题描述】:

我正在处理一个 angular 1.x.x 项目,并考虑将我的代码升级到 angular 2

现在在我的项目中,我有许多服务(工厂)来处理几乎将数据保存在 js 数组(缓存和存储)中的数据,并通过使用下划线处理数组来处理这些数据。

我在angular2中发现了很多使用ngrx的例子。

与使用数据服务处理数据相比,使用商店有什么好处?

如果我有多种数据类型(库存、订单、客户...),我的应用是否需要多个商店?

如何构建(设计)我的应用程序以处理此类多种数据类型?

【问题讨论】:

  • 以下答案似乎都没有解决关于存储优于数据服务的问题。嗯,一开始有多个 Flux 存储,基本上是服务,你以前用来存储数据,以某种方式提取和重构一些常见的样板逻辑。下一个进化步骤 Redux 将所有这些多个商店合并为一个。 store reducer、effects 等仍然包含您在服务中保留的相同逻辑,只是重新排列并包装在 store 中,为您提供访问数据的便捷方法。
  • 正如您在@LordTribual 的回答中看到的那样,我认为主要的重要好处是它使您紧贴一种模式,该模式确保数据仅由操作更改并且操作清晰/简单你的系统。数据服务无法确保(或不需要)这一点。在具有多个共享数据的系统中,这种模式非常有用。

标签: angular ngrx


【解决方案1】:

尽管您的问题主要是基于意见的,但我可以为您提供一些想法,为什么 ngrx 是一个不错的选择。尽管人们说将所有应用程序状态放在一个对象(单一状态树)中并不是一个好主意。但是,在我看来,无论如何,您的状态都会存在。有了一个商店,它就在一个地方,突变是明确的和跟踪的,而不是到处乱扔的,并由组件在本地维护。此外,您可以从应用程序中的商店中选择特定属性,因此您只能选择您关心的数据。如果您通过始终返回一个数组并使用 Observables 在您的 reducer 中实现不变性,您可以使用 ChangeDetectionStrategy OnPushOnPush 给你一个很好的性能提升。我们来看看下图取自Angular官方docs

如您所见,Angular 应用程序是使用组件架构构建的,这导致了组件树。组件上的OnPush 意味着只有当输入属性发生更改时,才会启动更改检测。例如,如果Child BOnPush 并且Child ADefault,并且您更改了Child A、@987654342 内部的某些内容@ 的变化检测器不会被触发,因为没有输入属性发生变化。但是,如果您更改 Child B 内部的某些内容,Child A 将被重新渲染,因为它具有默认的更改检测器。

关于性能和单一状态树的内容太多了。存储的另一个优点是您可以实际推断您的代码和状态更改。所以大多数 Angular 1.x 应用程序的现实是范围汤。这是来自 Lukas Ruebbelke 的 blog post 的精美图片:

图片显示它非常好。来自 Tero Parviainen 的另一位 article 谈到了他如何通过禁止 ng-controller 来改进他的 Angular 应用程序。这一切都与范围汤有关,管理不断变化的状态是一件困难的事。 redux 动机表示以下see here

如果一个模型可以更新另一个模型,那么一个视图可以更新一个模型, 这会更新另一个模型,而这反过来可能会导致另一个模型 查看更新。在某些时候,你不再明白会发生什么 在您的应用程序中,因为您无法控制何时、为什么以及如何 它的状态。当系统不透明且不确定时,很难 重现错误或添加新功能。

通过使用ngrx/store,您实际上可以解决这个问题,因为您将在您的应用中获得清晰的数据流。

由于ngrx 受到redux 的高度启发,我想说同样的main principles 应用:

  • 单一事实来源
  • 状态为只读
  • 使用纯函数进行更改

因此,在我看来,最大的好处是您能够轻松跟踪用户交互和状态变化的原因,因为您调度操作并且这些操作总是指向一个位置,而对于普通模型,您必须找到所有引用并查看更改内容和时间。

使用 ngrx/store 还可以让您使用 devtools 来查看调试状态容器并恢复更改。我想,时间旅行是 redux 的主要原因之一,如果你使用的是普通的旧模型,那是相当困难的。

@muetzerich 已经提到的可测试性也是使用 ngrx/store 的一个好处。 Reducers 是纯函数,这些函数很容易测试,因为它们接受输入并简单地返回输出,并且不依赖于函数外部的属性并且没有副作用,例如http 调用等

要跳到底线,我想说不需要使用 ngrx/store 来做任何这些事情,但你会受到限制(上面提到的三个原则),它提供了一个通用模式和带来不错的好处。

对于您的问题:

如果我有多种数据类型(库存、订单、客户...),我的应用是否需要多个商店?

不,我不建议使用多个商店。

如何构建(设计)我的应用程序以处理此类多种数据类型?

也许 Tero Parviainen 的 blog post 可以帮助您弄清楚如何设计您的商店。他解释了如何为示例应用设计应用状态树。

【讨论】:

  • 但是 Angular 2+ 有服务。您可以将它们用作单一事实来源,并将它们注入所有需要数据的组件中。 Redux 在 React 中很受欢迎,因为 React 缺少很多东西,比如“extraneous props”问题。本文讨论 ngrx 或其他商店对有限的 Angular 应用程序的好处有限:blog.angular-university.io/angular-2-redux-ngrx-rxjs
  • NgRx 需要权衡取舍。它通过大量不必要的样板代码成倍地增加了代码复杂性。另一方面,它几乎没有提供任何超出 Angular 开箱即用的功能。这篇博文涵盖了您决定是否需要它所需的所有信息:Angular Application State Management: You Do (Not) Need External Data Stores
【解决方案2】:

关于使用商店的好处的一个很好的解释你可以在那里找到documentation

集中式、不可变状态

所有相关的应用程序状态都存在于一个位置。这使得追查问题变得更加容易,因为错误时的状态快照可以提供重要的洞察力,并使重新创建问题变得容易。这也使得在 Store 应用程序上下文中难以解决的问题(如撤消/重做)变得微不足道,并支持强大的工具。

性能

由于状态集中在应用程序的顶部,因此数据更新可以通过依赖于存储切片的组件向下流动。 Angular 2 是为了优化这种数据流安排而构建的,并且可以在组件依赖未发出新值的 Observable 的情况下禁用更改检测。在最佳商店解决方案中,这将是您的绝大多数组件。

可测试性

所有状态更新都在 reducer 中处理,它们是纯函数。纯函数测试起来非常简单,因为它只是简单地输入,对输出进行断言。这样就可以测试应用程序的最关键方面,而无需使用模拟、间谍或其他会使测试变得复杂且容易出错的技巧。

多家商店?

IMO 使用一个商店并将您的数据类型作为属性添加到您的商店中。

【讨论】:

  • 这是一般的好处。我想比较旧方式(数据服务和具有存储数据类型的数组)。如果使用一个商店,我可以得到一个大类来处理我的应用程序中的所有操作。这不是个好主意吗?如何区分类型之间的代码?
  • 据我了解,您为每种数据类型编写 reducer,使用 provideStore 将其添加到 store,然后在组件中使用 store.select(myreducer)。
【解决方案3】:

ngrx.store 做了精心设计的组件/服务会做的事情,并带来额外的好处。到目前为止,我很早就开始研究它们是如何结合在一起的,这就是我发现的:

服务和组件很容易造成无法维护的混乱。如果您有级联操作、复杂的数据交互和对远程位置的调用,您最终会构建一个与 ngrx 中的 action-reducer-store 安排几乎相同的服务。小的纯函数、可观察对象等。ngrx 已经有了,为什么不使用它并从它所代表的思想和模式中获益。

如果强制/鼓励对小型可测试函数进行思考。为中等复杂的组件布置一个或多个 reducer 会强制执行一项规则,该规则将消除许多耗时的陷阱。没有什么比追踪源自回调队列的准多线程竞争条件更能耗费数小时的时间了。我确信这可能发生在 reducer 上,但它简化了对调用序列和状态的访问以进行调试。

Angular2 模式变得更容易。具有显示逻辑的模板,组件作为模板所需的所有点点滴滴的聚集地。服务变得更简单,因为它们只是进行远程调用或处理来自任何地方的数据的 io。然后是用于维护和更改状态的动作和减速器,这会触发所有其他部分响应新状态。我发现使用组件/服务模式,其中任何一个都将开始变得庞大而复杂,其副作用是变得非常难以调试。我的服务最终会存储状态并执行数据 io。

可观察的。 rxjs.store 中的一切都是可观察的,这是响应式应用程序的基础。将应用程序状态构建为 observable 有时有点晦涩难懂或不是很简单,但弄清楚并做好它会在以后产生巨大的收益。

我能看到的唯一负面因素是减速器很快就会变得非常大。似乎有很多情况会重复使用不同名称的相同代码。我的大脑尖叫着“带参数的函数”,但它不是那样工作的。另一方面,这是应用程序的结构和状态以所有细节表达的地方,所以那里肯定有很多。当出现问题时,不可避免地会出现问题,将纯函数作为问题的根源可以更容易地追踪和修复。

【讨论】:

  • 服务存储状态和执行数据 io 的缺点是什么?
  • 如果做得好,没有。例如,角度的 v4 到 v5 需要更新到 HttpClient。如果一项服务做得很好,它就像我的 ngrx 设置一样简单;在一个文件中更改标头代码和响应数据结构。在状态管理系统中添加自动保存、撤消/重做或离线操作等非常容易,如果您的服务以类似的方式构建,则也很容易。
猜你喜欢
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 2017-08-19
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 2017-03-29
  • 2017-10-08
相关资源
最近更新 更多