OnPush стратегия изменений

Стратегия изменений OnPush в Angular предназначена для оптимизации работы системы обнаружения изменений (change detection). По умолчанию Angular использует Default стратегию, проверяя весь компонентный дерево при любом событии, что может быть ресурсоёмко. OnPush ограничивает количество проверок, значительно повышая производительность.

Принципы работы OnPush

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

    • Входные свойства (@Input()) изменились по ссылке.
    • События внутри компонента (например, клики) вызывают изменения.
    • Происходит явный вызов markForCheck() или detectChanges() через ChangeDetectorRef.
  2. Изменения внутри объекта или массива не обнаруживаются автоматически, если ссылка объекта не изменилась:

    @Input() data: any[];
    
    // Это не вызовет повторного рендера
    this.data.push(newItem);
    
    // Нужно создавать новый объект
    this.data = [...this.data, newItem];

Применение OnPush

import { Component, ChangeDetectionStrategy, Input } from '@angular/core';

@Component({
  selector: 'app-item',
  template: `<div>{{ item.name }}</div>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ItemComponent {
  @Input() item: { name: string };
}
  • Angular будет проверять ItemComponent только если изменится объект item целиком.
  • Это особенно эффективно в больших списках и сложных интерфейсах с множественными компонентами.

Взаимодействие с асинхронными данными

При использовании Observables и async пайпа, OnPush интегрируется идеально:

<div *ngFor="let item of items$ | async">
  <app-item [item]="item"></app-item>
</div>
  • Любое новое значение потока инициирует повторную проверку только соответствующего компонента.
  • Изменения других частей интерфейса не вызывают лишних проверок.

Вызов изменений вручную

В случае сложных сценариев, когда данные изменяются внутри компонента без смены ссылки, используется ChangeDetectorRef:

constructor(private cdr: ChangeDetectorRef) {}

updateData() {
  this.data.push(newItem);
  this.cdr.markForCheck(); // Обновление OnPush компонента
}

Это позволяет сохранить преимущества OnPush, не жертвуя реактивностью интерфейса.

Преимущества и ограничения

Преимущества:

  • Существенное снижение количества проверок изменений.
  • Ускорение рендеринга больших и сложных приложений.
  • Предсказуемое поведение компонентов.

Ограничения:

  • Требует иммутабельных подходов к данным.
  • Нужен внимательный контроль за изменениями объектов и массивов.
  • Иногда приходится вручную инициировать проверку при асинхронных изменениях.

Эти два механизма — временные функции анимаций и OnPush стратегия изменений — являются ключевыми инструментами Angular для создания производительных и визуально плавных интерфейсов. Они требуют понимания внутренних принципов фреймворка и дисциплины в управлении состоянием компонентов и их визуальными переходами.