避免通过多个子组件传递数据并在 Angular 中缓存冗余数据 2

Avoid passing data through multiple child components and caching redundant data in Angular 2

据我所知,有两种方法可以从外部异步 Web API 调用我的组件来分发我的数据:

我有一个根应用程序组件,其中包含一些动态创建的 divs,它们显示内容和控件来回切换以查看不同的数据。向前和向后的切换是由我的控件控制的索引号实现的。

我的第一个方法 是在我的根组件中拆分对象数据并将其传递到我的自定义组件。像这样:

<controls></controls>
<div class="data-container" *ngFor="let data of data; let i = index">
  <div *ngIf="i === contentIndex">
    <general-information [generalInfo]="data.generalInformation"></general-information>
    <status-lights-container [statusInfo]="data.statusInformation"></status-lights-container>
    <textfields [textfields]="data.textFields"></textfields>
  </div>
 </div>

我创建了一个在我的应用程序组件中调用的服务,等待承诺,然后使用 *ngFor 遍历我的对象数据数组。我将数据传递到我的自定义组件并传递所需的数据。像这样:

import { Data } from './models/Data';
import { StatusService } from './services/status.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  data: Data[];

  constructor(private ss: StatusService) {
  }

  ngOnInit(): void {
    this.getData();
  }

  getData(): void {
    this.ss.getStatusData().then(status => { 
      this.status = status;
    });
  }
}

如您所见,我的应用程序根组件从未使用过任何数据,这些数据现在缓存在仅用于创建 HTML 和将数据传递给我的其他组件(我的服务应该做的事情)。在组件之间传递数据也很费力。

我也有这个问题,我的<status-lights-container>只是一个容器,它还会拆分数据并将其传递给其他自定义组件。所以我有更多未真正使用和缓存的数据。

我的第二种做法是调用服务函数获取数据,保存在服务中的一个变量中。然后将我的数据数组的长度传递给我的根应用程序组件,并在我的 HTML.

中创建此组件元素计数

<div class="content-container" *ngFor="let index of arrayLength; let i = index">
  <div *ngIf="i === contentIndex">
    <general-information [index]="index"></general-information>
    <status-lights-container [index]="index"></status-lights-container>
    <textfields [index]="index"></textfields>
  </div>
</div>

getData(): void {
 this.ss.getStatusData().then(length => { 
   this.arrayLength = length;
    });
}

现在我将根据它们接收到的 contentIndex 将保存在我的服务中的数据数组中的数据加载到我的组件中。

问题开始

ngOnInit() 在我启动网络 API 的地方被解雇,我如何等待异步调用在我的嵌套组件中完成,以便它们知道数据加载完成了吗?

如果我在我看来切换到另一个 data-container div,我只需从我的 <controls> 组件更改服务中的 contentIndex。但是我的 data-container 是如何得知这种变化的?

这通常是个好方法吗?还有其他建议吗?

我想达到和避免的事情

Edit: This is my status.service.ts after first suggestions in the answers:

import pnp from "sp-pnp-js";
import { BehaviorSubject, Observable } from 'rxjs/Rx';
import { Http } from "@angular/http";
import { Injectable } from '@angular/core';
import { Status } from './../models/status';
import { STATUS } from "app/models/mock-status";

@Injectable()
export class StatusService {
  status: BehaviorSubject <Status[]> = new BehaviorSubject(null);

 constructor(private http: Http) { }

  getStatusData(): Observable<Status[]> {
    return this.http.get("app/models/mock-status")
      .map((res: Status[]) => res.json() as Status[])
      .catch((err: Response) => Observable.throw(console.log(err)));
  }

  setStatus(status: Status[]): void {
    this.status.next(status);
  }

  getStatus(): Observable <Status[]> {
    return this.status.asObservable();
  }
}

状态服务

@Injectable()

export class StatusService {
  status: BehaviorSubject< class[] > = new BehaviourSubject(null);

  constructor(private http: Http) {}

  getStatusData(): Observable < class[] > {
    return this.http.get(parameters)
      .map((res: class[]) => res.json() as class[])
      .catch((err: Response) => Observable.throw(console.log(err)));
  }

  setStatus(status: class[]): void {
    this.status.next(status);
  }

  getStatus(): Observable < class[] > {
    return this.status.asObservable();
  }
}

AppComponent

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  data: Data[];

  constructor(private ss: StatusService) {}

  ngOnInit(): void {
    this.getData();
  }

  getData(): void {
    this.ss.getStatusData().subscribe((status: class[]) => {
      this.ss.setStatus(status);
    });
  }
}

这将开始从服务中获取值并将其存储在可观察对象中。您所要做的就是 Subscribe 来自其他子组件的数据,例如 getData() 做,当 Behavior 主题具有值时,它将把它们推送到订阅它的组件。作为一个额外的好处,它将存储最后一个值供以后使用,这样如果一个组件订阅之后它也会接收到数据。