web-dev-qa-db-ja.com

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

たとえば、service.tsにangularのコンテキスト外にあるfunction noificationHandler()があるとします。 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"_はアングルのゾーンの外側にあるため、このevent _("notification.msg")_が呼び出されたとき、angular sの変更検出は実行されません。

現在、変更検出を呼び出す2つの方法があります。

1)noificationHandler()をangleの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)detectChanges()は独自のコンポーネントの変更のみを検出しますか、または子コンポーネントの変更検出も実行しますか?

2)zone.run()は、ルートからリーフまでのすべてのコンポーネントの変更検出をトリガーしますか?

Zone.run()とdetectChanges()の中で、performance

25
Ajey

_ApplicationRef.tick_(setTimeout()と同じ)およびzone.run()は、アプリケーション全体の変更検出を引き起こします。また、Angularまたはby Angular(ビューバインディングまたは@HostBinding()を使用してアプリケーション全体の変更を検出します。

_ChangeDetectorRef.detectChanges_は、特定のコンポーネント(および、必要に応じて、たとえば入力バインディングのためにその子孫)の変更検出を実行します

Angularのゾーンの外側で実行されているコードがAngularのコードを呼び出して状態を変更する場合、Angularは状態が変更されたことを知る方法がないため、変更検出を明示的に呼び出す必要があります。

状態への変更がコンポーネント(コンポーネントフィールドなど)に対してローカルである場合、_ChangeDetectorRef.detectChanges_または_ChangeDetectorRef.markforCheck_の方が効率的です。

たとえば、外部からの呼び出しが別のルートにナビゲートする場合、これは多くのコンポーネントに影響を与える可能性があり、また、非同期呼び出し(およびコールバックが呼び出される)を引き起こす可能性があるため、ルート全体の変更がいつ完了するかは明確ではありません。この場合、zone.run()がより良いオプションです。直接および間接的に呼び出されるコード(オブザーバブルやプロミスのコールバックなど)は、Angularのゾーン内で実行され、Angularがそれらを認識します変更検出を自動的に呼び出します。

26

どちらもまったく異なるものです。

NgZoneは、インスタンスを複数のスコープで実行できるように、アプリのゾーンを提供するライブラリです。

ChangeDetectionは、A> B> Cのように常に親から葉へと移動します。detectChanges()を呼び出すと、現在のコンポーネントとその子コンポーネントも呼び出されます。したがって、これは、リーフコンポーネントにOnPush changesdetectionStrategyを使用するための最良のアプローチであるため、入力が更新されたときにのみChangesを検出します。

また、ApplicationRefはChangeDetectorに似ています。違いは、ルートコンポーネントから最後の子コンポーネントへの変更を検出することです。

ChaneDetectionとNgZoneは、不必要なChangeDetectionを避けるために常に最適な組み合わせです

6
Babar Bilal