Với OnPush, Angular chỉ kiểm tra component khi có một trong các tín hiệu: input thay đổi tham chiếu, event từ template của chính nó, async pipe phát giá trị, hoặc signal đọc trong template thay đổi. Ngoài các trường hợp đó, dù dữ liệu đã đổi, view vẫn giữ nguyên.
Ba nguyên nhân hay gặp:
// 1. mutate the input object instead of replacing it
this.user.name = 'new' // same reference → no check
this.user = { ...this.user, name: 'new' } // correct
// 2. state updated from outside the component template
this.socket.onMessage(msg => {
this.messages.push(msg)
this.cdr.markForCheck() // mark this component + ancestors dirty
})
// 3. subscribe manually and assign, instead of using the async pipePhân biệt hai API dễ nhầm:
- markForCheck(): đánh dấu component và chuỗi cha là dirty để vòng change detection kế tiếp kiểm tra. Đây là lựa chọn đúng cho OnPush.
- detectChanges(): chạy change detection ngay lập tức cho component và cây con. Nặng hơn và dễ gây lỗi NG0100 nếu gọi sai lúc.
Hướng bền vững hơn là chuyển state sang signal hoặc dùng async pipe — cả hai tự đánh dấu dirty, không phải nhớ gọi markForCheck thủ công.