5

目前正在重构 Angular 应用程序以使用 ngrx 存储并有两个选项。这是我们应用程序的基本结构。我相信大多数 Angular 应用程序都是以相同的方式构建的:

AppComponent
|-- ContainerComponent
    |-- ChildComponent1
    |   |-- GrandChildComponent
    |       |-- GrandGrandChildComponent
    |-- ChildComponent2

ContainerComponent 已注入Store<AppState>。我要解决的问题是 GrandGrandChildComponent(例如,DropDownMenu 组件)必须根据应用程序的状态更改其行为(即在商店中发生的某些条件下禁用某些菜单项)并在单击时发出事件在菜单项上,以便ContainerComponent(或任何其他组件,不是必需的祖先)可以对其做出反应。

有几种解决方法:

  1. @Input使用/在组件之间进行通信@Output
  2. 注入Store任何需要知道状态的组件

选项 1 是我在文档中读到的最常见/推荐的模式。所以只有 ContainerComponent 是胖的,所有的孩子都是瘦的/笨的,并且依赖于通过@Input.

但据我所知,这种方法添加了很多样板文件,您必须添加不必要的属性才能将状态传递给 Grand Child 组件。而且它还打破了关注点分离原则,因为任何中间组件都必须知道下面的组件需要什么。而且,如果它知道只有 Grand Components 上可用的详细信息,则制作通用组件并不容易。

另一方面,方法 2 似乎解决了分离关注点的问题,而且它似乎也是更清洁的实现。但由于我在使用redux模式方面相对较新,所以我不确定这是否是正确的方法,也许我不知道当我在重构方面过于深入时可能会遇到任何陷阱。

IMO,这两种方法都提供了一种简单的方法来测试每个组件,这对我来说非常重要。

我很怀疑采取哪种方法。我应该注意哪些陷阱?

谢谢

4

2 回答 2

4

以下是 redux 的创建者 Dan Abramov(ngrx 的灵感来自于 redux,因此很多相同的想法也适用于 ngrx)对这个话题的看法:

何时引入容器?我建议您首先使用演示组件开始构建您的应用程序。最终你会意识到你在中间组件传递了太多的道具。当您注意到某些组件不使用它们收到的道具而只是将它们向下转发并且您必须在孩子需要更多数据时重新连接所有这些中间组件时,现在是引入一些容器组件的好时机。通过这种方式,您可以获取叶组件的数据和行为道具,而不会增加树中间不相关的组件的负担。这是一个持续的重构过程,所以不要试图在第一次就把它做好。当您尝试使用此模式时,您将对何时提取一些容器有一种直观的感觉,

资料来源: https ://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#7dc5

于 2017-07-14T13:09:41.837 回答
1

这在很大程度上取决于您对每个组件的用例,无论它们有多少 @Output 和 @Input。

我已经使用您的第一种方法很长一段时间了,如果您的 Child / lower-order 组件进行非常简单的交互(自上而下获取数据,然后将 Event 返回给 Parent )或 Dumb 组件(只需要输入)。当然我的容器很大

但是,如果您的 Child 组件中的一个最终具有许多 I/O 并且具有许多其他子子组件也具有相同的内容,则您可能希望将它们视为 Big-Child (来自 Child 的 @Output() 将留在 Big -子组件而不是传递给 GrandParent 组件)

自下而上的过多 @Output() 也可能会让您头疼:)。第二种方法将使您的组件更易于阅读。

AppComponent |-- ContainerComponent |-- ChildComponent1 | |-- GrandChildComponent | |-- GrandGrandChildComponent |-- ChildComponentWithManyIO => Make them to be self-managed |--GrandChild with only Input |--GrandChild with many Inputs/Outputs ( Self-managed )

我管理状态的想法来自这里:https ://www.youtube.com/watch?v=eBLTz8QRg4Q

于 2017-07-17T18:22:07.020 回答