ngIf指令中的异步管道

When using the AsyncPipe inside of an *ngIf, if the Observable connected to the AsyncPipe pushes its values before the *ngIf becomes true, the value returned from the AsyncPipe will be incorrect.

例如,假设我有:

<div *ngIf="showPipe">
    <div *ngFor="let item of arrObs | async">{{item}}</div>
</div>

然后说事件按此顺序发生:

  1. showPipe is false
  2. arrObs pushes [1,2,3]
  3. showPipe is set to true

From what I've seen, the *ngFor will act as if arrObs | async returned null.

One solution to this problem is to use [hidden] instead, but there are a lot of benefits to *ngIf, like performance and making null handling easier.

正确的方法是什么?我是否应该根本不使用可观察对象来显示内容?我以为使用可观察的是最角度的工作方式。

评论
  • sit_in
    sit_in 回复

    Surround your structure in an ng-container which contains the async pipe and stores the value in a variable using as. Also use the ng-if directive to load the container only after you get a value in that async pipe.

    <ng-container *ngIf="( arrObs| async ) as array">
        <div *ngIf="showPipe">
            <div *ngFor="let item of array">{{item}}</div>
        </div>
    </ng-container>
    

  • 无言以对
    无言以对 回复

    There are some ways you can solve this. I would suggest adding a shareReplay operator on your Observable:

    readonly arrObs = this.someDataFromSomewhere().pipe(
      shareReplay(1)
    );
    

    这样,您将始终收到有关订阅的最新数据。

    There are also ways to handle this in the template and still maintain the *ngIf benefits:

    <ng-container *ngIf="arrObs | async as arr">
      <div *ngIf="showPipe">
        <div *ngFor="let item of arr">{{item}}</div>
      </div>
    </ng-container>
    

    Or if you don't want the *ngIf to wait for the observable

    <ng-container *ngIf="{ arr: arrObs | async } as data">
     <div *ngIf="showPipe">
       <div *ngFor="let item of data.arr">{{item}}</div>
     </div>
    </ng-container>