iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
Modern Web

Angular 常見問題大小事系列 第 14

Angular ngIf 與 Async Pipe

情境

當我們在 template 訂閱一組資料,而需要對它做一些邏輯處理的時後。

不好的方式

.ts

export class TemplateComponent {
  products$: Observable<any> = this.apiService.fetchProd();
  constructor(public apiService: ApiService) {}
}

.html

<ng-container *ngIf="products$ | async as products;">
  <ng-container *ngIf="products.length > 0; else empty">
    <ng-container *ngFor="let item of products"> ...略 </ng-container>
  </ng-container>
</ng-container>
<ng-template #empty> No Data </ng-template>

若像上述這樣的寫法,會造成重覆訂閱而增加 server 的負擔,所以在實作上,通常會避免這情況發生


解決方式

使用 ngIf as

將 html 寫法稍做修改

<ng-container *ngIf="(products$ | async)?.length > 0 as products; else empty">
  <ng-container *ngFor="let item of products"> ...略 </ng-container>
</ng-container>
<ng-template #empty> No Data </ng-template>

products$ | async 定義為 products
這樣就只會被訂閱一次,而這麼做的好處也可以使程式碼更容易閱讀,


加上 shareReplay

在 ts 檔裡加上 shareReplay
.ts

export class TemplateComponent {
  products$: Observable<any> = this.apiService.fetchProd().pipe(
      shareReplay()
  );
  constructor(public apiService: ApiService) {}
}

還有一點要注意的是,在 ng-container 裡,不能同時使用 ngIfngFor 否則會報錯唷唷唷~

明天會接續來說 ng-container 與 ng-template 這件事

附錄:RxJS Multicast 類 Operator (1) - multicast / publish / refCount / share / shareReplay


上一篇
Angular RxJs 各種解訂閱方式
下一篇
Angular ng-container 與 ng-template
系列文
Angular 常見問題大小事31

尚未有邦友留言

立即登入留言