Giới thiệu
Trong thời gian gần đây, tôi đã khám phá một số tính năng của Angular như effect, afterRenderEffect, afterNextRender, afterEveryRender và Renderer2. Mặc dù không phổ biến như các khái niệm khác như signals hay computed, nhưng việc hiểu cách và thời điểm sử dụng chúng là rất quan trọng. Bài viết này sẽ giúp bạn phân biệt và áp dụng chúng một cách hiệu quả trong dự án Angular của mình.
Mục lục
- Sử dụng
effect - Sử dụng
afterRenderEffect - Sử dụng
afterNextRendervàafterEveryRender - So sánh giữa
Renderer2vàafterEveryRender - Kết luận
- Câu hỏi thường gặp
Sử dụng effect
Hàm effect() sẽ chạy ít nhất một lần và sau đó mỗi khi có sự thay đổi trong signal phụ thuộc. Điều này có nghĩa là nếu bạn có nhiều signal phụ thuộc và bạn cập nhật chúng, effect sẽ chỉ chạy một lần. Điều này khác với Observables, nơi mà logic có thể được thực thi nhiều lần, dẫn đến các tác dụng phụ không mong muốn.
Ví dụ về effect
typescript
// trạng thái của giao diện người dùng
readonly theme = signal<'light' | 'dark'>('light');
constructor() {
effect(() => {
// thay đổi giao diện và lưu trữ
document.body.dataset.theme = this.theme();
localStorage.setItem('theme', this.theme());
});
}
Sử dụng afterRenderEffect
afterRenderEffect được khuyên dùng cho các cập nhật DOM hoặc các API trình duyệt, vì nó được thực thi sau khi Angular đã hoàn tất việc vẽ giao diện trong trình duyệt. Điều này rất hữu ích khi bạn cần thực hiện các thay đổi mà không thể thực hiện trên server.
Ví dụ về afterRenderEffect
typescript
constructor() {
afterRenderEffect({
earlyRead: () => this.scrollPercentage(),
write: (val) => {
const divTop = this.divTop();
if (divTop) {
divTop.nativeElement.innerText = `Scroll: ${val()}%`;
}
},
});
}
Sử dụng afterNextRender và afterEveryRender
Cả hai hàm này cho phép bạn đăng ký một callback sẽ được gọi sau khi Angular hoàn tất việc vẽ tất cả các thành phần vào DOM.
afterNextRenderchỉ chạy một lần sau khi Angular vẽ giao diện lần đầu tiên.afterEveryRendersẽ chạy sau mỗi chu kỳ render.
Ví dụ về afterNextRender
typescript
constructor() {
afterNextRender(() => {
const inputs = this.inputs();
const firstEmpty = inputs.find((d) => d.nativeElement.value == '');
firstEmpty?.nativeElement?.focus();
});
}
So sánh giữa Renderer2 và afterEveryRender
Khi quyết định giữa việc sử dụng Renderer2 hoặc afterEveryRender, bạn nên cân nhắc:
Renderer2được sử dụng khi bạn muốn gắn các listener hoặc thực hiện các thay đổi trực tiếp trên DOM.afterEveryRenderđược sử dụng khi bạn muốn thực hiện một callback sau khi DOM đã được vẽ xong.
Ví dụ về Renderer2
typescript
constructor() {
this.renderer.listen(this.divRef.nativeElement, 'scroll', () => {
// logic để theo dõi scroll
});
}
Kết luận
Tổng kết lại, các công cụ này không thay thế lẫn nhau mà bổ sung cho những nhu cầu khác nhau. Nếu logic của bạn hoàn toàn phản ứng, hãy sử dụng effect. Nếu phụ thuộc vào DOM, hãy dùng afterRenderEffect. Đối với các điều chỉnh DOM một lần sau khi vẽ đầu tiên, sử dụng afterNextRender. Nếu logic của bạn cần được thực hiện sau mỗi lần re-render DOM, hãy dùng afterEveryRender. Cuối cùng, Renderer2 là cách toàn diện để gắn listener và thao tác DOM mà không gặp rủi ro về SSR.
Hy vọng bài viết này cung cấp cho bạn cái nhìn sâu sắc về các tính năng này trong Angular. Nếu bạn có bất kỳ câu hỏi nào, hãy để lại ý kiến của bạn dưới bài viết này hoặc kết nối với tôi trên LinkedIn.
Câu hỏi thường gặp
1. effect() và afterRenderEffect có khác nhau như thế nào?
effect() được sử dụng cho trạng thái phản ứng, trong khi afterRenderEffect được dùng cho các thay đổi DOM sau khi Angular đã vẽ.
2. Có nên sử dụng Renderer2 trong mọi trường hợp không?
Không, bạn nên sử dụng Renderer2 khi cần can thiệp vào DOM, còn các hiệu ứng khác nên dùng các hàm đã đề cập ở trên.
3. afterNextRender có thể sử dụng với SSR không?
Không, afterNextRender chỉ chạy trên client sau khi DOM đã được vẽ.