web-dev-qa-db-fra.com

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

Disons que j'ai une function noificationHandler() dans mon service.ts qui est en dehors du contexte angulaire. noificationHandler() est invoqué par un tiers et noificationHandler() consomme essentiellement un tableau et émet le tableau vers les composants qui ont souscrit à son service.

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;
    });
}

^^^ à ce stade, le modèle n'est pas mis à jour avec les nouvelles données

Étant donné que "notification.msg" Est en dehors de la zone angulaire, angular s n'est pas exécutée lorsque cet événement ("notification.msg") Est appelé.

Il y a maintenant 2 façons d'invoquer la détection de changement.

1) En enveloppant la noificationHandler() à l'intérieur de la zone angulaire.run ()

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

2) En demandant individuellement au composant de détecter les changements

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

Les deux options fonctionnent! Et ma structure de composants est la suivante

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

Des questions -

1) detectChanges () détectera-t-il les modifications uniquement pour ses propres composants ou exécutera-t-il également la détection des modifications sur les composants enfants?

2) zone.run () déclenchera-t-il la détection de changement de tous les composants depuis la racine jusqu'à la feuille?

Parmi les zones.run () et detectChanges (), je suis curieux de savoir lequel est le meilleur dans performance?

25
Ajey

ApplicationRef.tick (Identique à setTimeout()) et zone.run() provoquent la détection des modifications sur l'ensemble de l'application. Les écouteurs d'événement ajoutés dans Angular ou par Angular (en utilisant les liaisons de vues ou @HostBinding()) provoquent une détection de changement pour toute l'application.

ChangeDetectorRef.detectChanges Exécute la détection des modifications pour un composant spécifique (et ses descendants le cas échéant, par exemple en raison de liaisons d'entrée)

Si du code exécuté en dehors de la zone d'Angular appelle le code d'Angular et change l'état, alors la détection de changement doit être invoquée explicitement parce que Angular n'a aucun moyen de savoir que l'état a changé.

Si la modification de l'état est locale à un composant (par exemple un champ de composants), ChangeDetectorRef.detectChanges Ou ChangeDetectorRef.markforCheck Sont plus efficaces.

Si l'appel de l'extérieur, par exemple, navigue vers un itinéraire différent, cela peut avoir des conséquences sur un certain nombre de composants, et il n'est pas clair non plus quand la modification de l'itinéraire complet est terminée car cela pourrait provoquer des appels asynchrones (et des rappels appelés). Dans ce cas, zone.run() est la meilleure option, car le code invoqué directement et indirectement (comme les rappels d'observables et de promesses) invoqué s'exécutera à l'intérieur de la zone angulaire et Angular les reconnaîtra et invoquer automatiquement la détection des modifications.

26
Günter Zöchbauer

Les deux sont des choses totalement différentes.

NgZone est une bibliothèque qui fournit des zones pour votre application afin que vous puissiez exécuter les instances dans plusieurs étendues.

ChangeDetection est toujours du parent à la feuille comme A> B> C Lorsque vous appelez detectChanges (), il appellera également le composant actuel et ses composants enfants. Il s'agit donc de la meilleure approche pour utiliser OnPush changesdetectionStrategy pour les composants feuilles, de sorte qu'ils ne détectent les changements que lorsque les entrées sont mises à jour.

De plus, ApplicationRef est similaire à ChangeDetector; la différence est qu'il détectera les changements du composant racine au dernier composant enfant.

ChaneDetection et NgZone est toujours la meilleure combinaison pour éviter les ChangeDetection inutiles

6
Babar Bilal