问题 Redux / ngrx / store架构:为什么不从哑组件调度操作?


我正在构建一个Angular 2 ngrx / store应用程序并试图了解最佳实践。

  • 我喜欢一个不可变状态,它只根据调度的动作进行更改,以便应用程序状态非常清晰且可调试。
  • 我喜欢从“智能”容器中向下流动的单向数据,因为这样我们就可以使用异步管道来减少对状态的检查。

但是我不明白为什么在将动作发送到商店之前我们想要将事件从哑组件“冒泡”到智能组件。是否有可重复使用组件的唯一原因?在我看来,大多数组件都不会被重复使用,因为在我想要包含CSS的所有内容完全相同的情况下并不多。我还缺少其他任何好处吗?从可维护性/可读性的角度来看,能够直接看到在发生交互的组件上发送的操作不是更好吗?


13102
2018-06-16 18:26


起源

使用ng> 2一段时间之后,我开始意识到ngrx / effect和smart-container是你有两种设计选择。如果您使用ngrx / effects,那么您不需要使用Smart-Dumb组件。 - Harshal Patil
可能重复 React / Redux - 保存选择值onChange - Paul Sweatte


答案:


我完全同意你的观点,我有同样的疑问。

我希望组件使用调度程序发出一个动作(用于 ngrx/store 是商店本身)而不是将此逻辑移动到容器(实际应用程序)。

这样,组件与容器分离,容器不需要知道操作:它只是监听状态更改并在必要时传递最终数据。

另一方面, ngrx / store简介 正在通过一个更智能的容器来推广设计,这个容器对底层组件有很多了解。

坦率地说, 我还没有看到一个明显的赢家:我只是认为来自组件的调度操作更简单,更清洁,更接近于 榆树建筑 这是Redux的灵感之一。


3
2018-06-30 07:57



查看Dan Abramov撰写的这篇文章(Redux的创建者之一) medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0 他声称他现在已经修改了他的方法,并乐于将“智能”组件嵌入“哑”组件中(尽管他现在使用不同的名称),并将其作为实现细节的智能 - Mark Whitfeld
谢谢,其实我已经读过了。但与此同时,我完全转向榆树和一些React Native,我重生了:D - pietro909


首先,我不是该主题免责声明的专家。 

  • 我觉得控制哑组件的智能组件实际上就是所谓的 中介模式。使用此模式可确保更少的组件必须处理 store,从而增强虱子耦合。
  • 易于维护:如果你必须重构和批量重命名动作,当动作出现在较少的地方时,这会更容易。
  • 有一个中心位置处理 actions 允许一个 快速概述 的架构。也热插拔了 store 访问逻辑可以更容易完成。
  • 正如已经提到的那样: 重用。您可以在具有或不具有ngrx体系结构的项目之间共享和重用哑组件。
  • 也可以通过不同的布线在同一个项目中重用 inputs 和 outputs。例如:A dropdownComponent 可能有很多需要不同输入和输出的用例。

5
2017-10-22 21:55





其中一个主要原因是重复使用。

就MVC而言,将您的智能组件视为您的控制器,将您的哑组件视为您的视图。

想象一个愚蠢的组件,它为你的一个实体(模型)呈现一个编辑表单。哑组件处理显示表单和验证消息,但是您可以在添加实体屏幕,编辑实体屏幕上重新使用该组件,也可以在应用程序中的其他位置重新使用弹出对话框。这些用例中的每一个都需要具有相同验证的相同形式,但您可能对“提交”执行非常不同的操作。在每种情况下,调用哑组件的智能组件可能是不同的智能组件。通过提升事件并将值传递给智能组件,您可以执行截然不同的操作,同时只编写“视图”一次。


3
2017-07-02 00:59



很好的答案,这是在不同用例中重复使用相同表单的一个很好的例子。 - Patrick H.


我想扩展给定的答案。

如果说没有来自哑组件的调度操作有助于重复使用,除了允许您一次又一次地使用您刚刚创建的相同组件之外,它还可以帮助您与第三方组件集成。这些可能是开源组件,甚至是您的同事可能会开发的,这些组件不知道您使用NgRx操纵数据的方式。 这样,您可以尽可能地使代码保持通用,模块化和独立于实现。

只是为了澄清,这都是关于建议的,在某些情况下,采取不同的行动可能会更聪明,但通常最好坚持惯例。


1
2018-03-15 19:33





我还没有找到任何关于“冒泡”事件的参考资料 NGRX /示例应用内。在Rob的谈话中,我还没有得到(我可能会错过一些东西)。

我只是使用所有的ngrx作为例子,现在它看起来很好。 ngrx / store用于存储数据,ngrx /效果用于链操作(我可以简化),以及“actions”图像中的“中间件”,用于描述您可以使用其中一个商店部件执行的操作。

然后,当我看起来最方便的时候我正在使用动作(我只是确保文件中使用的所有动作都与当前类相关)。


0
2018-06-16 18:51



例如,在book-detail.ts中,它会发出添加和删除事件。然后在其父组件(book-view.ts)中,它接受该事件并调度一个动作。为什么不直接在书籍细节中发送?这种情况并不是那么糟糕,因为它只是一个级别。但是如果你在一个更复杂的应用程序中有多个级别的组件,我可以看到输出事件的“冒泡”非常烦人。 - David
似乎所有愚蠢的组件都像md-input或button或者你可以得到的简单元素。您不希望将存储逻辑绑定到该组件,因为如果您决定更改有关您的操作,缩减器或效果或其他存储逻辑的内容,则需要更新您拥有的每个哑组件。如果将所有逻辑保留在“根”组件中(如页面 - 元素直接由路由器显示),则必须更新其中的少数(易于访问)。所以它基本上保持健康的应用程序。 - Piotr Grużewski
我不同意你的观点@PiotrGrużewski:我认为属于消息传递(然后是动作)的逻辑应尽可能隐藏,以便容器可以只关注实际应用程序的逻辑而不是基础架构。在我看来,将事件暴露给容器然后将它们转化为行动是多余的。另一方面,我认为让组件直接使用商店还不是一个完美的解决方案:我们可能需要一个合适的调度员? - pietro909
@David:关于带有组件的CSS,我会说它不会影响可重用性,因为它通常会覆盖它。不应修改的是代码,这肯定会破坏捆绑。 - pietro909