Giới thiệu
Trong các ứng dụng Angular, dữ liệu thường cần được chuyển đổi trước khi hiển thị cho người dùng. Dù là định dạng ngày tháng, chuyển đổi kiểu chữ hay tạo các chuyển đổi tùy chỉnh, Angular Pipes cung cấp một cách đơn giản và rõ ràng để thực hiện điều này mà không làm rối rắm các template hay logic nghiệp vụ của bạn.
Trong bài viết này, chúng ta sẽ tìm hiểu:
- Lợi ích của việc sử dụng Angular Pipes
- Các loại Pipes tích hợp và tùy chỉnh kèm ví dụ
- Cách Angular Pipes ảnh hưởng đến hiệu suất
- Các phương pháp tốt nhất để tối ưu hóa Pipes trong các ứng dụng thực tế
Angular Pipes là gì?
Angular Pipe là một tính năng cho phép bạn chuyển đổi dữ liệu trong các template. Pipes được viết dưới dạng các hàm đơn giản nhưng có thể được áp dụng trong template bằng toán tử | (pipe operator).
Ví dụ:
html
<p>{{ user.name | uppercase }}</p>
Ở đây, pipe uppercase sẽ chuyển đổi user.name thành chữ hoa trước khi hiển thị.
✅ Pipes giúp tách biệt logic chuyển đổi dữ liệu khỏi logic nghiệp vụ của component.
✅ Chúng làm cho các template của bạn trở nên sạch sẽ và dễ đọc hơn.
Tại sao nên sử dụng Angular Pipes?
- Cú pháp khai báo: Thay vì viết logic chuyển đổi trong component, bạn có thể áp dụng trực tiếp trong template.
html
<!-- Không dùng pipe -->
<p>{{ formatDate(user.dob) }}</p>
<!-- Dùng pipe -->
<p>{{ user.dob | date }}</p>
- Tính tái sử dụng: Một pipe tùy chỉnh có thể được sử dụng lại trong nhiều component mà không cần viết lại logic.
- Cải thiện khả năng đọc: Giữ cho các template đơn giản và giảm sự lộn xộn.
- Lợi ích hiệu suất: Pipes thuần túy được cache và chỉ thực thi khi các đầu vào thay đổi, giúp giảm thiểu việc tính toán không cần thiết.
Các loại Angular Pipes
1. Pipes tích hợp sẵn
Angular cung cấp một số pipes tích hợp sẵn rất hữu ích.
📌 Ví dụ 1: DatePipe
html
<p>{{ today | date:'fullDate' }}</p>
<!-- Kết quả: Thứ Bảy, ngày 12 tháng 9 năm 2025 -->
📌 Ví dụ 2: CurrencyPipe
html
<p>{{ price | currency:'USD':'symbol' }}</p>
<!-- Kết quả: $150.00 -->
📌 Ví dụ 3: DecimalPipe
html
<p>{{ pi | number:'1.2-2' }}</p>
<!-- Kết quả: 3.14 -->
📌 Ví dụ 4: PercentPipe
html
<p>{{ 0.25 | percent }}</p>
<!-- Kết quả: 25% -->
📌 Ví dụ 5: SlicePipe
html
<p>{{ 'AngularPipes' | slice:0:7 }}</p>
<!-- Kết quả: Angular -->
📌 Ví dụ 6: AsyncPipe
Pipe async đăng ký với một Observable/Promise và tự động xử lý việc hủy đăng ký.
html
<p>{{ user$ | async }}</p>
2. Pipes tùy chỉnh
Khi các pipes tích hợp không đủ, bạn có thể tạo các pipes tùy chỉnh của riêng mình.
Ví dụ: Một pipe để viết hoa chữ cái đầu tiên của mỗi từ
typescript
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'capitalize'
})
export class CapitalizePipe implements PipeTransform {
transform(value: string): string {
if (!value) return '';
return value
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
}
Sử dụng trong template:
html
<p>{{ 'angular pipes blog' | capitalize }}</p>
<!-- Kết quả: Angular Pipes Blog -->
Hiệu suất và Pipes
Mặc dù pipes đơn giản hóa logic của template, việc sử dụng chúng không đúng cách có thể ảnh hưởng đến hiệu suất.
✅ Pure vs Impure Pipes
-
Pure Pipes (Mặc định): Chỉ được thực thi khi đầu vào thay đổi và lưu kết quả cho cùng một giá trị đầu vào. Phù hợp trong hầu hết các trường hợp.
-
Impure Pipes: Được thực thi trong mỗi chu kỳ phát hiện thay đổi (ngay cả khi đầu vào không thay đổi). Hữu ích khi làm việc với dữ liệu có thể thay đổi (ví dụ: mảng/đối tượng thay đổi tại chỗ). Sử dụng quá nhiều có thể ảnh hưởng tiêu cực đến hiệu suất.
typescript
@Pipe({
name: 'filter',
pure: false // Pipe không thuần túy
})
✅ Các phương pháp tốt nhất về hiệu suất
- Ưu tiên Pure Pipes: Luôn giữ pipes thuần túy trừ khi thực sự cần thiết.
- Tránh logic phức tạp trong Pipes: Pipes nên nhẹ. Di chuyển các tính toán nặng sang dịch vụ hoặc quản lý trạng thái.
- Sử dụng AsyncPipe: Thay vì đăng ký/hủy đăng ký thủ công với các Observables:
html
<p>{{ user$ | async }}</p>
- Tránh Impure Pipes cho việc lọc/sắp xếp danh sách lớn: Thay vì:
html
<li *ngFor="let item of items | filter:searchText">{{ item }}</li>
Tốt hơn: Lọc dữ liệu một lần trong component và gán nó.
typescript
this.filteredItems = this.items.filter(i => i.includes(this.searchText));
- Sử dụng TrackBy với NgFor:
html
<li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li>
Kết luận
Angular Pipes là một công cụ mạnh mẽ để chuyển đổi và hiển thị dữ liệu trong các template. Bằng cách hiểu sự khác nhau giữa pipes tích hợp và tùy chỉnh, và tuân theo các phương pháp tốt nhất về hiệu suất, bạn có thể:
- Giữ cho các template sạch sẽ và dễ bảo trì
- Đạt được khả năng tái sử dụng tốt hơn
- Đảm bảo hiệu suất tối ưu trong các ứng dụng lớn
✅ Điểm mấu chốt: Sử dụng Angular Pipes cho việc định dạng và chuyển đổi đơn giản. Giữ cho chúng thuần túy, nhẹ và tận dụng async cho các Observables để khai thác tối đa lợi ích hiệu suất.