0

所以我有这样的场景(简化)

  • 主要成分
  • 列表组件
  • 列表服务

在哪里:

主要成分

<my-list [month]="month"></my-list>

列表组件html

<li *ngFor="let item in list | async></li>

列出组件 ts

list: Observable<ListItem[]>;
@Input() month: string;
...
ngOnInit() {
  this.list = this._listService.list;
}
ngOnChanges(changes: SimpleChanges) {
  if (changes.month && !!this.month) {
     this._listService.getAllByMonth(this.month);
  }
}

最后列出服务

private _list: BehaviorSubject<ListItem[]>;
list: Observable<ListItem[]>;

private dataStore: {
  list: ListItem[]
};

constructor(private _http: HttpClient) {
  this.dataStore = { list: [] };
  this._list= <BehaviorSubject<ListItem[]>>new BehaviorSubject([]);
  this.list= this._list.asObservable();
}

public getAllByMonth(month: string) {
   this._http.get<ListItem[]>(environment.apiPath + 'list/' + month)
    .subscribe(
      data => {
        this.dataStore.list = data;
        this._list.next(Object.assign({}, this.dataStore).list);
      },
      error => console.log('Could not load the list.')
    );
}

出于某种原因,getAllByMonth 被调用了很多次......即使我只将月份值更改为 1。

当月份值发生变化时,应该如何安排 getAllByMonth 调用 ONCE 的东西?

4

1 回答 1

2

*ngFor使用等于===比较来查看Array实例是否已更改。当新数组和旧数组不是同一个引用时,则重新创建集合中的所有元素。

告诉*ngFor它不应该重新创建一个元素,而是重新使用数组中的一个元素。您必须使用trackBy回调函数。

<li *ngFor="let item in list | async; trackBy: trackItem"></li>

然后在你的组件中

public trackItem(indx: number, item: LinkItem): number {
     return item.id;
}

此函数需要返回一个产生true相等===比较的值(数字、字符串、对象等)。这就是如何ngFor知道它应该重新使用具有该数组项的组件。

在我上面的例子中,我假设它们是一个唯一的数字id,可以从每个LinkItem.

所有这些都会停止递归调用,ngOnChanges因为每次list使用新的数组实例更新这些组件时都会重新创建这些组件。

于 2018-05-29T16:43:08.933 回答