angular:绑定方法+模板中带有异步管道的参数

时间:2019-04-13 01:00:48

标签: angular firebase angularfire2

我正在使用firebase和多对多中间人收集模式。参见:https://angularfirebase.com/lessons/firestore-nosql-data-modeling-by-example/#Many-to-Many-Middle-Man-Collection

但是在集合中获得一组ID之后,我正在努力寻找一种模式来“完成连接”。

我想使用async pipe在模板中呈现“ joined”元素,如下所示:

<div *ngFor="let id of itemIds">
  <div *ngIf="(getById$(id) | async) as item">{{item.name}}</div>
</div>

但是Angular change detection多次调用getById$(),每次都获得一个新的Observable,并且...浏览器冻结。

我通过缓存Observable破解了一个解决方案,但这似乎不正确。

  getById$(uuid:string):Observable<T>{
    this['get$_'] = this['get$_'] || {};      // cache in component
    const cached$ = this['get$_'][uuid];
    if (cached$) return cached$ as Observable<T>;
    return this['get$_'][uuid] = this.get(uuid) as Observable<T>;
  }

有更好的模式吗?

1 个答案:

答案 0 :(得分:0)

让我们按逻辑进行播放。 *ngFor集合中使用的所有项目必须保持不变,以防止更改检测重新呈现项目视图,从而避免重新订阅可观察对象。因此,您必须在某处保留一组可观测值,而不是即时创建它们。完成此操作的方式几乎是您实际需要的。我们可以改善它,尽管改善不多。

当您获得itemIds集合时,您只需执行一次即可将它们映射到包含可观察对象的某个集合,然后将该集合放入模板中,而不仅仅是源ID。像这样:

private _items: any[] = []; // put your type here instead of <any>

get items$(): any[] {
    return this._items;
}

set itemIds(value: any[]) {

    if (!value) {
        this._items = [];
        return;
    }

    // I know that it's pretty ugly and inefficient implementation,
    // but it'll do for explaining the idea.
    this._items = value.map(id => {
        // this is the essential part: if observable had already been created for the id
        // then you _must_ preserve the same object instance in order to make change detection happy
        // you can also try to use trackBy function in the *ngFor definition
        // but I think that it will not help you in this case
        let item$ = this._items.find(i => i.id === id);
        if (!item$) {
            item$ = {
                id: id,
                obs$: this.getById(id)
            };
        }
        return item$;
    });

}

然后在模板中:

<div *ngFor="let item$ of items$">
    <div *ngIf="(item$.obs$ | async) as item">{{item.name}}</div>
</div>

通过这种方式,可观察对象的ID保持不变,并且整个事物都可以在更改检测中正常工作。

因此,总而言之:您需要保留一组可观察对象,并且仅在id的源集合发生更改时进行更新,并且需要为它们创建的id保留可观察的实例。