Что такое стратегия обнаружения изменений (Change Detection)?angular-45

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

Как работает Change Detection

  1. Цель: Определить, какие части приложения нуждаются в обновлении
  2. Триггеры:
    • События (клики, таймеры)
    • HTTP-запросы
    • Асинхронные операции (Promise, Observable)
  3. Процесс:
    • Angular создает дерево компонентов
    • Проверяет изменения в данных компонентов
    • Обновляет DOM при обнаружении изменений

Основные стратегии

1. Default

@Component({
  selector: 'app-default',
  template: `...`,
  changeDetection: ChangeDetectionStrategy.Default
})

Особенности:

  • Проверяет все компоненты при любом асинхронном событии
  • Глубокое сравнение объектов (по ссылкам)
  • Может снижать производительность в сложных приложениях

2. OnPush

@Component({
  selector: 'app-onpush',
  template: `...`,
  changeDetection: ChangeDetectionStrategy.OnPush
})

Особенности:

  • Проверяет компонент только когда:
    • Изменяются входные свойства (@Input)
    • Происходит событие внутри компонента (click и т.д.)
    • Явно вызван метод markForCheck()
    • Асинхронные события в шаблоне (async pipe)
  • Работает только с иммутабельными данными
  • Значительно повышает производительность

Как Angular определяет изменения

  1. Zone.js:
    • Монопатит асинхронные операции
    • Уведомляет Angular о необходимости проверки
  2. ChangeDetectorRef:
    • Позволяет управлять процессом вручную

Методы управления ChangeDetectorRef

constructor(private cdr: ChangeDetectorRef) {}

// Отключает проверку для компонента и его дочерних
detach()

// Включает проверку снова
reattach()

// Помечает компонент для проверки в следующем цикле
markForCheck()

// Выполняет проверку немедленно
detectChanges()

Пример использования OnPush

@Component({
  selector: 'app-user',
  template: `
    <div>{{ user.name }}</div>
    <button (click)="update()">Update</button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserComponent {
  @Input() user: User;

  update() {
    // Для иммутабельного обновления:
    this.user = {...this.user, name: 'New Name'};
  }
}

Лучшие практики

  1. Используйте OnPush везде, где возможно
  2. Иммутабельность данных — ключ к работе OnPush
  3. Async pipe — автоматически запускает обнаружение
  4. Избегайте сложных вычислений в шаблоне
  5. Ручное управление — только когда необходимо

Проблемы и решения

Проблема: Медленная работа приложения
Решение: Переход на OnPush, иммутабельные структуры

Проблема: Изменения не отображаются
Решение:

  • Убедитесь в иммутабельности данных
  • Используйте markForCheck()
  • Проверьте async pipe

Резюмируем

Change Detection в Angular:

  • Default: Проверяет все компоненты всегда (простота vs производительность)
  • OnPush: Проверяет только при явных изменениях (оптимизация)
  • Zone.js: Отслеживает асинхронные операции
  • ChangeDetectorRef: API для ручного управления

Оптимальный подход:

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class OptimizedComponent {
  data$ = this.service.data$; // Используйте async pipe

  constructor(
    private service: DataService,
    private cdr: ChangeDetectorRef
  ) {}
}