Перейти к содержанию

Механизм ChangeDetection

Отслеживание изменений — это механизм в Angular, который отвечает за изменение выражений в шаблонах при их изменении в моделях.

Механизм запускается каждый раз, когда, например, инициируется одно из браузерных событий, выполняются HTTP-запросы или вызывается функция setTimeout() или setInterval().

В случае с браузерными событиями, Angular расширяет стандартный метод addEventListener(), добавляя после вызова "оригинального" обработчика события запуск отслеживания изменений.

На самом деле ключевую роль здесь играет библиотека zone.js. В Angular с ее помощью все приложение разделяется на секторы, каждый из которых запоминает контекст асинхронного выполнения. Такой подход после завершения асинхронной операции позволяет запустить механизм отслеживания изменений в нужном секторе.

Запуск механизма ChangeDetection в родительском компоненте автоматически инициирует запуск механизма во всех дочерних компонентах.

ChangeDetectionStrategy

В Angular есть два варианта работы алгоритма отслеживания изменений:

  • OnPush;
  • Default (используется по умолчанию).

Алгоритм задается в свойстве changeDetection объекта конфигурации декоратора @Component() и указывается для каждого компонента отдельно. Если параметр не указан, используется алгоритм Default (механизм отслеживания изменений запускается при любом действии пользователя или изменения состояния приложения).

Стратегия OnPush указывается в основном для компонентов, которые предназначены для отображения каких-либо статических данных.

Использование стратегии OnPush подразумевает, что механизм отслеживания изменений запустится только в момент создания компонента (стадия жизненного цикла OnChanges) и при каждом последующем изменении его входных свойств (предваряются декоратором @Input() и передаются извне).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Component({
    selector: 'book-item',
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: ` <h1>{{ book }}</h1> `,
})
export class BookItemComponent implements OnChanges {
    @Input() book: string = null;

    constructor() {}

    ngOnChanges() {
        console.log(this.book);
    }
}

Такой подход используется в целях повышения эффективности работы приложения за счет снижения количества вызовов механизма ChangeDetection.

Попробуйте изменить входное значение для BookItemComponent и посмотрите на результат.

Сервис ChangeDetectorRef

В библиотеке @angular/core есть сервис ChangeDetectorRef. Он позволяет взять управление механизмом отслеживания изменений полностью под свой контроль.

Основные методы сервиса:

  • detach() — полностью отключает механизм ChangeDetection;
  • detectChanges() — принудительно запускает механизм отслеживания изменений;
  • reattach() — используется после вызова detach() для активации механизма ChangeDetection.

Действие всех трех методов распространяется только на тот компонент, в пределах которого вызываются эти методы.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Component({
    selector: 'manual-detection',
    template: `
        <h1>{{ book }}</h1>

        <button (click)="applyChanges()">Apply</button>
    `,
})
export class ManualDetectionComponent {
    book: string = 'Great Expectations';

    constructor(
        private changeDetection: ChangeDetectorRef
    ) {
        this.changeDetection.detach();

        this.book = 'Old Man & Sea';
    }

    applyChanges() {
        this.changeDetection.detectChanges();
    }
}

Здесь изначально отключается механизм отслеживания изменений. Затем переменной book присваивается новое значение, но в шаблоне изменения будут видны только после нажатия кнопки Apply, которая инициирует принудительный запуск механизма ChangeDetection.

Ссылки

Комментарии