Ban biên tập CodeReady
Kiến Thức Chuyên Sâu Angular Cho Lập Trình Viên Frontend
Khám phá kiến trúc cốt lõi, best practice về quản lý trạng thái, tối ưu hiệu năng và các lỗi thường gặp khi phát triển ứng dụng Angular quy mô lớn.
Angular là một nền tảng và framework phát triển ứng dụng web mạnh mẽ được xây dựng bằng TypeScript. Đối với lập trình viên Frontend, việc nắm vững cách Angular biên dịch, quản lý dependency injection và kiểm soát vòng đời component là chìa khóa để xây dựng các ứng dụng có khả năng mở rộng cao và bảo trì tốt.
Kiến Trúc Cốt Lõi Và Cơ Chế Thay Đổi Trạng Thái
Hiểu rõ cơ chế Change Detection là nền tảng để tối ưu hóa hiệu năng ứng dụng Angular. Mặc định, Angular sử dụng Zone.js để theo dõi các sự kiện bất đồng bộ và kích hoạt quá trình kiểm tra thay đổi trên toàn bộ cây component từ gốc đến ngọn.
Chiến Lược OnPush Change Detection
Để cải thiện hiệu năng, lập trình viên nên chuyển sang sử dụng chiến lược OnPush. Khi áp dụng chiến lược này, component chỉ được kiểm tra lại khi:
- Tham chiếu của một
@Inputthay đổi. - Component hoặc một trong các component con phát sinh sự kiện DOM.
- Một Observable được liên kết qua pipe
asyncphát ra giá trị mới. - Hàm
markForCheck()được gọi thủ công.
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-user-profile',
template: '<p>{{ user.name }}</p>',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserProfileComponent {
@Input() user: { name: string };
}Quản Lý State Và Dependency Injection
Dependency Injection (DI) trong Angular là một thiết kế mô hình mạnh mẽ giúp tách biệt logic xử lý và giao diện. Từ các phiên bản gần đây, Angular cung cấp hệ thống inject function hiện đại, giúp việc khai báo dependency gọn gàng và tường minh hơn.
Best Practice Cho Dependency Injection
- Sử dụng
providedIn: 'root'cho các Singleton service để hỗ trợ tính năng tree-shaking, loại bỏ mã thừa khi không sử dụng. - Khai báo service ở mức độ component nếu state của service cần được khởi tạo và hủy theo vòng đời của component đó.
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class DataService {
private http = inject(HttpClient);
getData() {
return this.http.get('/api/data');
}
}Các Lỗi Thường Gặp Và Cách Khắc Phục
Trong quá trình phát triển dự án thực tế, lập trình viên thường gặp một số vấn đề gây rò rỉ bộ nhớ hoặc sụt giảm hiệu năng nghiêm trọng.
Lỗi Rò Rỉ Bộ Nhớ Do Observable Không Unsubscribe
Khi đăng ký nhận dữ liệu từ Observable trong component mà không hủy đăng ký (unsubscribe) khi component bị hủy, ứng dụng sẽ tiếp tục tiêu tốn tài nguyên bộ nhớ.
Cách khắc phục: Luôn sử dụng pipe async trong template để Angular tự động quản lý việc đăng ký và hủy đăng ký, hoặc sử dụng toán tử takeUntil kết hợp với một Subject trong ngOnDestroy.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { DataService } from './data.service';
@Component({
selector: 'app-data-list',
template: '<div>Danh sách dữ liệu</div>'
})
export class DataListComponent implements OnInit, OnDestroy {
private destroy$ = new Subject<void>();
private dataService = inject(DataService);
ngOnInit() {
this.dataService.getData()
.pipe(takeUntil(this.destroy$))
.subscribe(data => {
// Xử lý dữ liệu
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}Checklist Phỏng Vấn Angular Cho Frontend
- Giải thích được sự khác biệt giữa Zone.js và cơ chế Zone-less trong các phiên bản Angular mới.
- Nắm vững các lifecycle hooks quan trọng như
ngOnInit,ngOnChanges, vàngOnDestroy. - Hiểu rõ cách cấu hình Lazy Loading cho các module hoặc component định tuyến (Routes).
- Biết cách viết Unit Test sử dụng Jasmine và Karma hoặc Jest cho component và service.