Hack Frontend Community

Как работает Change Detection в Angular?

Что такое Change Detection?

Change Detection — это механизм Angular, который следит за изменениями данных и обновляет шаблон (DOM), если нужно.

Когда в приложении что-то изменяется — Angular запускает процесс обнаружения изменений и сравнивает значения в компоненте с тем, что уже отрисовано, чтобы определить, нужно ли перерендерить DOM.


Как это работает?

  1. Angular запускает проверку с самого корневого компонента.
  2. Проходит по дереву компонентов вниз.
  3. Проверяет каждый биндинг ({{ value }}, [property], (event)) на изменения.
  4. Если значение изменилось — обновляется DOM.

Что запускает Change Detection?

Angular использует библиотеку zone.js, чтобы автоматически "захватывать" события, вызывающие изменения:

Источник измененияПример
События DOMclick, input, change, и т.д.
ТаймерыsetTimeout, setInterval
HTTP-запросыHttpClient
Promise и async/awaitfetch().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.

Change Detection Strategies

Angular поддерживает две стратегии обнаружения изменений:

СтратегияОписание
DefaultAngular проверяет все компоненты при любом изменении
OnPushAngular проверяет компонент только при изменении Input-параметров или событиях

Использование OnPush:

@Component({
  selector: 'app-optimized',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<p>{{ user.name }}</p>`
})
export class OptimizedComponent {
  @Input() user!: { name: string };
}

Это уменьшает количество проверок, повышая производительность, особенно в больших приложениях.

Как Angular сравнивает значения?

Angular использует сравнение по ссылке (shallow reference check):

this.user.name = "John"; // не триггерит OnPush!
this.user = { name: "John" }; // триггерит, потому что новая ссылка

Чтобы обновить компонент со стратегией OnPush — нужно создать новый объект.

Как оптимизировать Change Detection?

  • Используйте ChangeDetectionStrategy.OnPush везде, где это возможно.
  • Избегайте частых мутаций объектов/массивов (используйте иммутабельность).
  • Используйте trackBy в *ngFor, чтобы избежать лишних перерендеров.
  • Работайте с ChangeDetectorRef и NgZone для ручного управления:
constructor(private cdr: ChangeDetectorRef) {}

update() {
  this.value = newValue;
  this.cdr.detectChanges(); // вручную инициируем проверку
}

Важно:

OnPush не означает, что компонент никогда не будет обновляться. Он всё ещё реагирует на изменения входных данных и события (click, input).