前言

Pipe 是 Angular 中用來轉換資料的方式, 讓我們可以在 Template 中對資料進行格式化或轉換, 並且可以在程式碼中重複利用. 這篇文章將介紹內建 Pipe 和如何建立自訂 Pipe.

Pipe 用途

Angular 的 Pipe 是一種轉換資料的方式, 它可以用在 Template 中對資料進行格式化或轉換等操作, 並可以在程式碼中進行重複利用.

Pipe 可以分為兩種類型:

  • Angular 內建 Pipe: Angular 提供如 DatePipeUpperCasePipe
  • 自訂 Pipe: 開發者自行建立的 Pipe

內建 Pipe

只需要在模板中使用管道符號 | 來調用 Pipe 即可. 以下是一些常用的內建 Pipe:

DatePipe

格式化日期.

<p>{{ today | date:'yyyy-MM-dd' }}</p>
<!-- 輸出:2023-03-17 -->

<p>{{ today | date:'fullDate' }}</p>
<!-- 輸出:Friday, March 17, 2023 -->

UpperCasePipe / LowerCasePipe

將文字轉為大寫或小寫.

<p>{{ name | uppercase }}</p>
<!-- 輸出:JOHN -->

<p>{{ name | lowercase }}</p>
<!-- 輸出:john -->

CurrencyPipe

格式化金額.

<p>{{ price | currency:'USD' }}</p>
<!-- 輸出:$1,234.56 -->

<p>{{ price | currency:'TWD':'symbol-narrow' }}</p>
<!-- 輸出:NT$1,234.56 -->

PercentPipe

格式化百分比.

<p>{{ rate | percent }}</p>
<!-- 輸出:75% -->

<p>{{ rate | percent:'1.2-2' }}</p>
<!-- 輸出:75.50% -->

DecimalPipe

格式化數字.

<p>{{ number | number:'1.2-2' }}</p>
<!-- 1.2-2 表示:至少 1 位整數,2-2 位小數 -->

AsyncPipe

處理非同步資料 (Observable 或 Promise).

<p>{{ data$ | async }}</p>

在 Component 中:

import { Observable } from 'rxjs';

export class AppComponent {
  data$: Observable<string>;
  
  constructor(private http: HttpClient) {
    this.data$ = this.http.get<string>('/api/data');
  }
}

自訂 Pipe

可以自行撰寫 Pipe, 擴充 Angular 的 Pipe 功能. 需要實作 PipeTransform Interface, 該介面只有一個 transform 方法, 負責處理資料轉換.

建立自訂 Pipe

使用 Angular CLI 建立:

ng generate pipe double

範例: 建立一個將數字乘以 2 的 Pipe

import { Pipe, PipeTransform } from "@angular/core";

// Pipe 裝飾器
@Pipe({
  name: "double"
})
// 實作 PipeTransform Interface
export class DoublePipe implements PipeTransform {
  transform(value: number): number {
    return value * 2;
  }
}

使用方式:

<p>{{ 5 | double }}</p>
<!-- 輸出:10 -->

帶參數的 Pipe

Pipe 也可以接收參數.

範例: 建立一個可以指定倍數的 Pipe

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "multiply"
})
export class MultiplyPipe implements PipeTransform {
  transform(value: number, multiplier: number = 1): number {
    return value * multiplier;
  }
}

使用方式:

<p>{{ 5 | multiply:3 }}</p>
<!-- 輸出:15 -->

<p>{{ 5 | multiply }}</p>
<!-- 輸出:5 (使用預設值 1) -->

實用範例: 文字截斷 Pipe

建立一個截斷長文字的 Pipe:

import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: "truncate"
})
export class TruncatePipe implements PipeTransform {
  transform(value: string, limit: number = 50, ellipsis: string = '...'): string {
    if (!value) return '';
    if (value.length <= limit) return value;
    return value.substring(0, limit) + ellipsis;
  }
}

使用方式:

<p>{{ longText | truncate:20 }}</p>
<!-- 只顯示前 20 個字元,後面加上 ... -->

鏈結多個 Pipe

可以將多個 Pipe 串連使用:

<p>{{ today | date:'fullDate' | uppercase }}</p>
<!-- 先格式化日期,再轉大寫 -->

<p>{{ price | currency:'USD' | lowercase }}</p>

Pure Pipe vs Impure Pipe

預設情況下, Pipe 是 Pure Pipe, 只有在輸入值改變時才會重新執行. 如果需要在每次變更檢測時都執行, 可以設定為 Impure Pipe:

@Pipe({
  name: "myPipe",
  pure: false  // 設定為 Impure Pipe
})
export class MyPipe implements PipeTransform {
  transform(value: any): any {
    // 處理邏輯
  }
}

注意: Impure Pipe 會影響效能, 應謹慎使用.

總結

Angular Pipe 是格式化和轉換資料的強大工具:

  • 內建 Pipe: 提供常用的日期、數字、文字格式化功能
  • 自訂 Pipe: 可以建立符合需求的資料轉換邏輯
  • 可串連使用: 多個 Pipe 可以組合使用
  • 支援參數: Pipe 可以接收參數來客製化行為

善用 Pipe 可以讓 Template 更加簡潔, 提高程式碼的可讀性和可維護性.

參考資料