Angular 2+: Стратегия обнаружения изменений
Angular 2+: Стратегия обнаружения изменений

Angular 2+: Стратегия обнаружения изменений

Front-end 07.07.2020

Стратегия обнаружения изменений – это механизм Angular, который отвечает за изменение в шаблонах при изменении в моделях, то-есть как именно будут выглядеть компоненты в результате различных событий – браузерное события, promices, timers, XHR и т.д.

В Angular для обнаружения изменений используется библиотека Zone.js, которая запускает цикл обнаружения изменений при завершении событий. Метод onMicrotaskEmpty выполняет tick, который в свою очередь запускает механизм change detection.

this.zone.onMicrotaskEmpty
    .subscribe(() => {
        this.zone.run(() => this.tick());
})

В Angular есть 2 метода обнаружения изменения:

  1. Default
  2. OnPush

В случае Default стратегии обнаружения изменений, при каких-либо изменениях, проверка будет запущена по всем компонентам. В результате такой проверки новые значения сравниваются со старыми и, в случае их отличия, они будут изменены.

Запуск механизма ChangeDetection в родительском компоненте автоматически инициирует запуск механизма во всех дочерних компонентах. Такая проверка называется “dirty check” (“грядной проверкой”). В результате на каждом компоненте Angular будет сравнивать новые значения со старыми и обновлять представление, если они не равны.

Альтернативой существует стратегия изменения OnPush, в результате которой компонент будет зависеть только от входных параметров @Inputs().

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

Числа, булевые, строки, null и undefined это примитивные типы, в таком случае стратегия обнаружения изменения будет запущена сразу по изменению значения параметра Input, а объекты, массивы, и функции передаются по ссылке, таким образом для обнаружения изменений нужно будет изменить ссылку на объект.

Для того, что бы стратегия обнаружения OnPush работала корректно, разберемся что такое mutable и immutable объекты. Отличие immutable объекта заключается в том, что мы не можем изменить свойство объекта без изменения самого объекта, в таком случае достаточно будет сравнить ссылки на объект для Inputs, что бы понять, что объекты не равны.

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

Метод detectChanges() класса ChangeDetectorRef – говорит Angular, что нужно запустить процесс обнаружения изменений в этом компоненте и его потомках.

export class AComponent {
 @Input() inputAProp;

 constructor(public cd: ChangeDetectorRef) {
   this.cd.detach();
 }

 ngOnChanges(values) {
   this.cd.detectChanges();
 }

Метод tick() класса ApplicationRef – говорит Angular, что нужно запустить процесс обнаружения изменений во всем приложении.

export class AppComponent {
  constructor(private appRef: ApplicationRef) {
    ...
  }

  updateApplication() {
    this.appRef.tick();
  }
}

Метод markForCheck() класса ChangeDetectorRef – отмечает, что этот компонент и его родители должны быть проверенны при следующем цикле запуску проверки изменений.

export class AppComponent {
  constructor(private cd: ChangeDetectorRef) {
    ...
  }

  ngOnInit() {
    this.opStream.subscribe(() => {
        this.cd.markForCheck();
    })
}
}

Источники: angular.io, angular-university.io, bitsrc.io, thoughtram.io, habr.com, www.coldfox.ru, bxnotes.ru, itnext.io, metanit.com

Поделиться

Отправить ответ

avatar
  Получать новые комментарии  
Уведомлять о новых комментариях