Change Detection — это механизм, который отвечает за синхронизацию состояния данных (модели) и их отображения (представления) в Angular приложении.
Как работает Change Detection
- Цель: Определить, какие части приложения нуждаются в обновлении
- Триггеры:
- События (клики, таймеры)
- HTTP-запросы
- Асинхронные операции (Promise, Observable)
- Процесс:
- 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 определяет изменения
- Zone.js:
- Монопатит асинхронные операции
- Уведомляет Angular о необходимости проверки
- 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'};
}
}
Лучшие практики
- Используйте OnPush везде, где возможно
- Иммутабельность данных — ключ к работе OnPush
- Async pipe — автоматически запускает обнаружение
- Избегайте сложных вычислений в шаблоне
- Ручное управление — только когда необходимо
Проблемы и решения
Проблема: Медленная работа приложения
Решение: Переход на 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
) {}
}