2017-05-07 63 views
15

注意:为了简单起见,考虑部件的深度为:角2 +/4/5:智能,哑和深深嵌套组件通信

- Smart (grand)parent level 0 
    - dumb child level 1 
    .... 
    - dumb grandchild level 2 
     ....) 

有多种方案和条件如何智能/隆重/父/子组件在多层(至少3层)链上进行通信并传递数据。我们希望保留我们的'聪明'(大)父母组件作为唯一可以访问我们的数据服务(或原子/不可变的商店)的组件,它将促进与'愚蠢'(大)孩子交换信息。我们看到的选项是:

  1. 反模式(?):通过@ Input/@输出绑定将数据传递给组件链。这就是有些人称之为“无关属性”或“自定义事件冒泡问题”的问题(例如:herehere。)问题。不行。
  2. 反模式:智能组件通过@ViewChildren或@ContentChilden访问哑(大)孩子。这再次硬化了孩子们,并且仍然没有为(大)孩子们创建一个干净的机制来将数据传递给智能组件。
  3. 共享消息服务描述在angular.io食谱here和一个很好的帖子here

现在在'3'的情况下,哑(大)孩子必须注入消息服务。这使我想到了我的问题:

问题1:对于每个'愚蠢'(大)孩子来说,注入消息服务似乎很奇怪。对于消息服务来说,最好的做法是为这个家庭提供一个专门的服务,还是在上面提到的'智能'祖父母的数据服务上捎带? Q1A:另外,如果所有组件都会注入一个服务,如何比添加@ Input/@ Output绑定更好? (我看到“愚蠢的”组件需要某种方式来获取信息的观点)

Q2:如果'聪明'祖父母正在与一个类似redux的商店(我们的ngrx)进行通信怎么办?最好通过注入/专用消息服务与“哑”组件进行通信,或者最好是将商店注入每个“哑”组件......或者,注意,除了数据(即将数据添加到/更新存储或服务)之外,组件间通信是“动作”(例如:表单验证,禁用按钮等)的组合。

非常感谢!

回答

7

寻找这个进一步,当它涉及到如何最好地向下一个嵌套的组件链沟通和高达所以以后,似乎真的只有两种选择 - 之间的浮士德式的交易:

  • 要么通@输入/输出@绑定向上,向下,并在整个嵌套组件链(即处理的“定制事件冒泡”的问题或“外来属性”)

OR

  • 使用消息传递/订阅服务在此系列组件(很好的说明here)之间进行通信并为链中的每个组件注入该服务。

我个人是利用智能和表现('愚蠢')组件的支持者。名义上,一个“愚蠢的”组件只需要@Inputs和@Outputs就是这样。它并不关心组件树的深度或浅度 - 这是应用程序问题。事实上,它并不关心应用程序首先使用它。同时,如果向应用程序注入特定服务,深层组件不是非常笨拙或不可移植。顺便说一句,对手'聪明'组件真的是提供中介服务(通过第一类@Injectable服务或类似存储)到其需要它的家族树中的任何哑组件。只要孙子们以某种方式发出需要采取的服务行为(再次通过@ Input/@输出链),智能组件也不关心其直接孩子的@Inputs之外的组件。这样一个智能组件也可以跨应用程序线传输。

鉴于此,Faustian的讨价还价IMO倾向于利用@ Input/@ Output链来解决所带来的所有问题。也就是说,如果有人知道任何情况,我会密切注意这一点,并欢迎提供干净和分离的替代方案。

0

为什么#1是反模式?祖父母组件拥有数据并通过@Input参数将其传递给哑子组件。当一个事件发生时(通过@Output事件发射器),哑元子组件简单地调用回调,导致祖父母组件操纵数据。看起来很干净。

编辑:我看到你关于通过许多中间层重复传递值提交处理程序的观点。也许可以在父组件中创建代表组件树的嵌套结构。然后,每个组件可以传递它所需的属性,再加上一个对象传递给下一个组件。然后每个组件只知道它下面的一个:

// Parent component builds this object (or gets a service to do it) 

viewModelForChildComponent: { 

    property1NeededForChildComponent, 

    property2NeededForChildComponent, 

    viewModelForGrandChildComponent: { 
     property1NeededForGrandChildComponent, 

     property2NeededForGrandChildComponent, 

     viewModelForGrandGrandChildComponent: { 
      property1NeededForGrandGrandChildComponent, 

      submitHandlerNeededForGrandGrandChildComponent 
     } 
    } 
} 
+0

感谢您的想法。请注意,再次就解耦问题而言,海事组织除了提供间接服务是其主要职责之外,顶级部门不应该真正关心或了解其孙辈。顺便说一句,这与我原来的问题中的选项'2'没有太大差别。 – MoMo

+0

不客气。我想我明白你的意思了 - 顶层父组件现在不仅需要知道子组件需要什么,而且还需要知道其确切的层次结构。我个人对此表示赞同,因为我将这种协调视为父组件的工作。或者我创建一个服务将JSON转换为包含表示数据/回调(适用于单元测试)的分层视图模型。你是对的,这有点像你的第二选择,但没有真正触摸视图的孩子。无论如何,我很好奇你怎么最终解决这个问题。祝你好运! –

0

Input()和Output()绑定也是处理这种情况的完全合法的方式。让智能组件处理生成值的逻辑,然后使用Input()和Output()简单地传递和接收组件链上的值。

当然,这指出了智能/视图方法的缺点之一:更多的文件;更多的样板。这就是为什么我不会争辩一种适合所有人的单一方法。相反,选择一种在当前环境中有意义的方法(针对应用程序和组织)。

+0

我已经添加了为什么最好解耦嵌套组件链中的属性绑定的链接。但是很明显,如果有一个提交/清除按钮组件嵌套4层,其整个存在的理由是发出“提交”,为什么中间组件需要知道或关心其他问题?我同意普遍认为这是一种反模式。但是,如果水平深度只有1,那么我不会看到通过@ Input/@ Outputs传递数据的问题。 – MoMo

+0

编辑我的答案,以扩大专家委员会讨论多一点,并解决您提出的问题。 – Muirik