PassFront
  1. PassFront
  2. База знаний
  3. Change Detection

Как работает change detection в Angular и чем отличаются стратегии Default и OnPush?

Change Detection

Change detection — механизм, который определяет, что изменились данные, и обновляет DOM. Angular проверяет привязки шаблонов компонента, сравнивая текущие значения с предыдущими.

Откуда запускается проверка

Раньше за этим следила библиотека Zone.js: она перехватывает асинхронные события (клики, таймеры, XHR/fetch) и после каждого запускает проверку всего дерева компонентов сверху вниз. В новых версиях можно работать без Zone.js (zoneless), опираясь на сигналы и явные уведомления.

Default

Проверяются все компоненты при каждом событии. Просто и надёжно, но на больших деревьях тратит время.

OnPush

Компонент проверяется только если:

  1. изменилась ссылка на входное свойство @Input() (сравнение по ссылке, а не по содержимому);
  2. событие произошло внутри самого компонента или его обработчика;
  3. сработал async pipe или обновился сигнал, прочитанный в шаблоне;
  4. проверка запущена вручную через ChangeDetectorRef.markForCheck().
@Component({
  selector: 'app-user',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `{{ user.name }}`,
})
export class UserComponent {
  @Input() user!: User;
}

Типичная ошибка OnPush

Мутация объекта не обновит представление:

this.user.name = 'Ivan';          // ссылка прежняя — не обновится
this.user = { ...this.user, name: 'Ivan' }; // новая ссылка — обновится

Поэтому с OnPush используют неизменяемые данные.

Как управлять вручную

  • markForCheck() — пометить компонент и предков для проверки.
  • detectChanges() — проверить поддерево немедленно.
  • detach() / reattach() — отключить и вернуть проверку.

Зачем OnPush

Сокращает число проверок и ускоряет приложение; хорошо сочетается с async pipe, сигналами и иммутабельным состоянием.

Коротко для собеседования

Default проверяет все компоненты на каждое событие, OnPush — только при смене ссылки в @Input, событии внутри, async pipe или сигнале. Для OnPush данные делают неизменяемыми или вызывают markForCheck().

Другие вопросы раздела