Angular 4 组件通信 - child 到 parent 与订阅者

Angular 4 component communication - child to parent with subscriber

我正在尝试在 angular 4 中的 parent/child 组件之间共享服务数据。我有一个工作代码,但我不清楚这是否是最佳选择。我正在使用可注入服务 class 通过创建主题和订阅可观察方法在 parent --> child 之间进行通信。现在向后交流 i:e child --> parent,我 re-using 相同的服务 class 通过在 [=45= 中创建 Subjects 和订阅 observable ].这样我就订阅了 child 和 parent 中的 observables,这是正确的方法吗?我在其他地方看到人们建议使用@Output 装饰器在 child --> parent 之间进行通信,但我的代码使用的是订阅机制。以后会不会出现内存泄露等问题?

Parent 组件

  constructor(private _textdataservice: TinyEditorService, private _gmapService: GmapService) {
this.subscription = this._gmapService.getMessageC2P().subscribe((message) => {
  this.message = message;
  this.childCallingParent(message);
});
this.subscription = this._gmapService.getStoreSearchRequest().subscribe((radius) => {
  this.radius = radius;
  this.retrieveNearByLocations(radius);
});

}

Child 组件 -->

  constructor(private _gmapService: GmapService) {
// subscribe to home component messages
this.mainSubscription = this._gmapService.getMessageP2C().subscribe((addresses) => {
  this.mainCoordinates = addresses;
});

this.storeSubscription = this._gmapService.getMessageP2CStore().subscribe((addresses) => {
  this.storeCoordinates = addresses;
  if(this.storeCoordinates){
    for(let coord of this.storeCoordinates){
      this.addNearbyStoremarker(coord.name, coord.latitude, coord.longitude);
    }
  }
});

}

服务-->

export class GmapService {
  private _dataurl='/assets/gmapmarkers.json';
  constructor(private _http: Http){}

  private parentSubject = new Subject<IGmapData[]>();
  private storeSubject = new Subject<IGmapData[]>();
  private childSubject = new Subject<String>();
  private radiusSubject = new Subject<number>();

  sendMessageP2C(latLngArray: IGmapData[]) {
    this.parentSubject.next(latLngArray);
  }

  sendMessageP2CStore(latLngArray: IGmapData[]) {
    this.storeSubject.next(latLngArray);
  }

  sendMessageC2P(message: string) {
    this.childSubject.next(message);
  }

  requestNearByLocations(radius: number) {
    this.radiusSubject.next(radius);
  }

  clearMessage() {
    this.parentSubject.next();
    this.childSubject.next();
  }

  getMessageP2C(): Observable<IGmapData[]> {
    return this.parentSubject.asObservable();
  }

  getMessageP2CStore(): Observable<IGmapData[]> {
    return this.storeSubject.asObservable();
  }

  getMessageC2P(): Observable<string> {
    return this.childSubject.asObservable();
  }

  getStoreSearchRequest(): Observable<number> {
    return this.radiusSubject.asObservable();
  }

  getStoreMarkers(): Observable<IGmapData[]> {
      return this._http.get(this._dataurl)
        .map((response: Response) => <IGmapData[]> response.json());
  }
}

您可以在 ngOnDestroy 生命周期挂钩中取消订阅以防止内存泄漏,如以下答案所述:[

但是除非您需要这种额外的复杂性,否则使用 @Output 和 EventEmitter 可能是个好主意。

我会说,如果您需要在父子之间来回通信,最好使用@Input() 和@Output()。 原因是 Angular 会在您的组件出现或消失时为您 destroy/create 订阅。 当您需要在没有 parent/child 关系的组件之间广播事件时,Subjects 就派上用场了。 Subject 使用的一个例子是 facebook。当收到一条消息时,页面的多个部分将对该事件作出反应,但彼此之间没有关联。

但是,如果您实施 ngOnDestroy 来取消订阅您的主题,那应该可以使您的解决方案保持整洁。 使用主题方法的风险是最终会在您的应用程序中创建数百个主题,这可能会导致性能问题。

@Input 当您从 child.

的 child 传递时,@Output 可能会很慢并且变得复杂

如果您也想在其他组件中使用该数据,存储方法更好、更灵活。