Angular2 zone.run() vs ChangeDetectorRef.detectChanges()

Скажем, у меня есть function noificationHandler() в моем service.ts, который находится вне контекста angular. noificationHandler() вызывается третьей стороной, а noificationHandler() в основном потребляет массив и испускает массив компонентам, которые подписались на его службу.

service.ts

    public mySubject: Subject<any> = new Subject();
    public myObservable = this.mySubject.asObservable();

    constructor() {
       this.registry.subscribe("notification.msg",this.noificationHandler.bind(this));
    }

    noificationHandler(data) {
       this.publishUpdate(data)
    }

    publishUpdate(data) {
       this.mySubject.next(data);
    }

component.ts

constructor(private service: myService) {
    this.service.myObservable.subscribe(list => {
        this.list = list;
    });
}

^^^ в этот момент шаблон не обновляется новыми данными

Так как "notification.msg" находится вне зоны angular, angular s изменение не запускается, когда вызывается это событие ("notification.msg").

Теперь есть два способа вызвать обнаружение изменений.

1) Обернув noificationHandler() внутри angular zone.run()

 this.registry.subscribe("a2mevent.notification.msg", this.ngZone.run(() => this.noificationHandler.bind(this)));

2) путем индивидуального запроса компонента на обнаружение изменений

constructor(private service: myService, private ref: ChangeDetectorRef) {
    this.service.myObservable.subscribe(list => {
        this.list = list;
        this.ref.detectChanges(); // <==== manually invoking change detection
    });
}

Оба варианта работают! И моя структура компонента выглядит следующим образом

A --> root component
B
C
D // my component is here (4 levels of nesting)

Вопросы -

1) Будет ли обнаружение изменений() обнаруживать изменения только для своих собственных компонентов или будет также запускать обнаружение изменений на дочерних компонентах?

2) будет zone.run() инициировать обнаружение изменений всех компонентов от корня до листа?

Среди zone.run() и detectChanges() Мне интересно, что лучше в производительности?

Ответ 1

ApplicationRef.tick (то же, что и setTimeout()), и zone.run() вызывают обнаружение изменений для всего приложения. Кроме того, прослушиватели событий, добавленные в Angular или Angular (с использованием привязок вида или @HostBinding(), вызывают обнаружение изменений для всего приложения.

ChangeDetectorRef.detectChanges запускает обнаружение изменений для конкретного компонента (и его потомков, если применимо, например, из-за привязок ввода)

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

Если изменение состояния является локальным для компонента (например, поля компонентов), ChangeDetectorRef.detectChanges или ChangeDetectorRef.markforCheck являются более эффективными.

Если вызов извне, например, перемещается на другой маршрут, это может иметь последствия для нескольких компонентов, а также неясно, когда все изменения маршрута завершены, потому что это может вызвать асинхронные вызовы (и вызываемые вызовы), В этом случае zone.run() является лучшим вариантом, так как код, который прямо и косвенно вызывается (например, обратные вызовы наблюдаемых и promises), запускается внутри зоны углов, а Angular распознает их и автоматически вызывает обнаружение изменений.

Ответ 2

Оба совершенно разные вещи.

NgZone - это lib, который предоставляет зоны для вашего приложения, чтобы вы могли запускать экземпляры в несколько областей.

ChangeDetection всегда от родителя до листа A > B > C Когда вы вызываете detectChanges(), он вызывает текущий компонент и его дочерние компоненты. Таким образом, это лучший подход к использованию OnPush changesdetectionStrategy для компонентов листа, поэтому они будут только обнаруживать изменения, когда входы обновляются.

Кроме того, ApplicationRef похож на ChangeDetector; разница в том, что он обнаружит изменения от корневого компонента до последнего дочернего компонента.

ChaneDetection и NgZone - лучшая комбинация всегда, чтобы избежать ненужного ChangeDetection