具有深层组件层次结构的角度组件输出/事件

Jon*_*ter 1 javascript angular

我正在研究一个复杂的Angular2应用程序,我正在尝试遵循一个纯粹的,可重用的,"哑"组件的模式,这个组件由一个更大的"智能"组件包裹,该组件处理API交互(或与我的无功商店同步,或者其他否则处理外部依赖).

我的一个子组件<yet-another-presentational-component>(请参阅下面的代码)发出一个需要与API同步的事件.但是,它在其他不同组件中的深度为3级.这会产生一个问题,因为现在每个包含的组件<yet-another-presentational-component>都必须处理它的事件,以便将它们传递给智能父组件.这看起来非常糟糕; 如果有关如何<yet-another-presentational-component>发出的变化,那么我必须更新几个组件.

在另一方面,如果我注入我ApiService<yet-another-presentational-component>(从而使其成为"智能"组件),这将解决我的活动"桶式"的问题,而造成另一个问题:现在<yet-another-presentational-component>是不是可重复使用.此外,它违反了演示/智能组件的合同(据我所知,至少).

使用Angular1,至少$scope.$emit(或要求父母)可以用来解决这个问题.我怎么能重新设计这个小部件,以避免事件"桶旅",同时还坚持"智能"与"哑"组件的良好模式.

<!-- Sample app markup architecture -->

<smart-component-with-api-access>

   <dumb-presentational-component-1 (changeStatus)="handleStatusChange($event)">

       <dumb-presentational-component-details (changeStatus)="handleStatusChange($event)">

           <yet-another-presentational-component (changeStatus)="handleStatusChange($event)">

           </yet-another-presentational-component>

       <dumb-presentational-component-details>
   </dumb-presentational-component-1>
</smart-component-with-api-access>
Run Code Online (Sandbox Code Playgroud)

And*_*ker 5

有关组件交互的指南非常有用:

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

您应该使用服务,而不是简单的输出事件.然后,yet-another-presentational-component可以发出对服务的更改,同时 smart-component-with-api-access可以订阅服务并相应地采取行动.

例:

一个简单的通知服务"notification.service.ts":

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class NotificationService {

  constructor() { }

  private notificationSource = new Subject<string>();

  public notificationReceived = this.notificationSource.asObservable();

  notify(newMessage: string) {
    this.notificationSource.next(newMessage);
    console.log(message);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在smart-component-with-api-access中导入服务,添加到构造函数并订阅通知:

import { NotificationService } from './shared/services/notification.service';
...
export class SmartComponentWithAPIAccess {

  constructor(private notificationService: NotificationService) {

    this.notificationService.notificationReceived.subscribe(
      message => {
        // do something with message such as access API
      }
    );  
  }
}
Run Code Online (Sandbox Code Playgroud)

另一个演示组件中导入通知服务并在构造函数中声明如上所述,然后当您要触发通知/事件时:

this.notificationService.notify("I have a message");
Run Code Online (Sandbox Code Playgroud)