Як працює виявлення змін в Angular?
Що таке виявлення змін?
Виявлення змін — це механізм Angular, який моніторить зміни даних і оновлює шаблон (DOM), якщо це необхідно.
Коли щось змінюється в додатку — Angular ініціює процес виявлення змін і порівнює значення компонентів з тим, що вже відрендерено, щоб визначити, чи потрібно оновлювати DOM.
Як це працює?
- Angular починає перевірку з кореневого компонент.
- Пересувається вниз по дереву компонентів.
- Перевіряє кожне зв'язування (
{{ value }},[property],(event)) на зміни. - Якщо значення змінилося — DOM оновлюється.
Що ініціює виявлення змін?
Angular використовує бібліотеку zone.js для автоматичного "захоплення" подій, що викликають зміни:
| Джерело змін | Приклад |
|---|---|
| Події DOM | click, input, change тощо. |
| Таймери | setTimeout, setInterval |
| HTTP запити | HttpClient |
| Promise та async/await | fetch().then(...), await |
| Внутрішні зміни | this.value = ... |
Приклад: Автоматичне оновлення DOM
@Component({
selector: 'app-example',
template: `<p>{{ counter }}</p> <button (click)="increment()">+</button>`
})
export class ExampleComponent {
counter = 0;
increment() {
this.counter++;
}
}Angular автоматично відстежує зміну counter після натискання кнопки і оновлює DOM.
Стратегії виявлення змін
Angular підтримує дві стратегії виявлення змін:
| Стратегія | Опис |
|---|---|
Default | Angular перевіряє всі компоненти при будь-якій зміні |
OnPush | Angular перевіряє компонент лише тоді, коли змінюються параметри Input або відбуваються події |
Використання OnPush:
@Component({
selector: 'app-optimized',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<p>{{ user.name }}</p>`
})
export class OptimizedComponent {
@Input() user!: { name: string };
}Це зменшує кількість перевірок, покращуючи продуктивність, особливо в великих додатках.
Як Angular порівнює значення?
Angular використовує порівняння за посиланням (поверхневе порівняння):
this.user.name = "John"; // не ініціює OnPush!
this.user = { name: "John" }; // ініціює, бо нове посиланняЩоб оновити компонент зі стратегією OnPush — потрібно створити новий об'єкт.
Як оптимізувати виявлення змін?
- Використовуйте
ChangeDetectionStrategy.OnPushскрізь, де це можливо. - Уникайте частих мутацій об'єктів/масивів (використовуйте незмінність).
- Використовуйте
trackByв*ngFor, щоб уникнути непотрібних повторних рендерингів. - Працюйте з
ChangeDetectorRefтаNgZoneдля ручного управління:
constructor(private cdr: ChangeDetectorRef) {}
update() {
this.value = newValue;
this.cdr.detectChanges(); // вручну ініціювати перевірку
}Важливо: OnPush не означає, що компонент ніколи не оновлюватиметься. Він все ще реагує на зміни вхідних даних і події (клік, введення).
Важливо: Використання ChangeDetectorRef.detectChanges() вважається поганою практикою, оскільки воно порушує автоматичний механізм виявлення змін, ініціює непотрібний рендеринг, який може не бути необхідним, і створює непередбачувану поведінку. Для оптимізації зазвичай використовують markForCheck() або detach/reattach (ніколи не бачив останнього на живому проекті).
Angular має механізми реактивного програмування: сигнали, обсервації та вхідні дані. Краще використовувати їх для коректного рендерингу.
Читати більше тут.
Зміст
Що таке виявлення змін?Як це працює?Що ініціює виявлення змін?Приклад: Автоматичне оновлення DOMСтратегії виявлення змінЯк Angular порівнює значення?Як оптимізувати виявлення змін?
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.