【问题标题】:Angular 4 component communication - child to parent with subscriberAngular 4 组件通信 - 带有订阅者的子到父
【发布时间】:2018-05-12 14:06:18
【问题描述】:

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

父组件

  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);
});

}

子组件 -->

  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());
  }
}

【问题讨论】:

    标签: angular parent-child angular2-observables


    【解决方案1】:

    如果您需要在父母和孩子之间来回交流,我会说最好使用@Input() 和@Output()。 原因是 Angular 会在你的组件出现或消失时为你销毁/创建订阅。 当您需要跨没有父/子关系的组件广播事件时,主题就派上用场了。 主题使用的一个例子是 facebook。当收到一条消息时,页面的多个部分将对该事件做出反应,而不会相互关联。

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

    【讨论】:

      【解决方案2】:

      您可以在 ngOnDestroy 生命周期挂钩中取消订阅以防止内存泄漏,如以下答案所述:[how to unsubscribe several subscriber in angular 2

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

      【讨论】:

      • 感谢您的回复。我已经在父母和孩子中使用 ngOnDestroy。也同意这样一个事实,即父子之间的 2 路 pub-sub 不是一个好主意,因为我没有在网上找到单一的实现。我可以使用@output 装饰器,但希望将代码保留在服务类中的一个位置。我应该在孩子中使用输出装饰器吗?
      • @Output 属性将在子组件中,但前提是您直接在子组件和父组件之间传递数据,而不是通过某些外部服务。
      【解决方案3】:

      @Input @Output 可能会很慢,并且当您从 child 的 child 传递时会变得复杂。

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

      【讨论】:

      • 通过商店你的意思是服务方法@vineet?
      猜你喜欢
      • 2018-03-15
      • 2018-03-23
      • 1970-01-01
      • 2021-02-25
      • 2017-10-13
      • 2021-10-24
      • 1970-01-01
      • 2018-09-15
      • 2016-04-12
      相关资源
      最近更新 更多