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

dites que j'ai un function noificationHandler() à mon service.ts qui est en dehors du contexte d'angular. noificationHandler() est invoqué par un tiers et noificationHandler() consomme essentiellement un tableau et l'émet aux composants qui ont souscrit à son service.

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

composant.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

puisque le "notification.msg" est en dehors de la zone d'angular, angular s la détection de changement n'est pas exécutée lorsque cet événement ("notification.msg") est invoqué.

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

1) en enveloppant le noificationHandler() à l'intérieur de la zone d'angular.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 composant est comme suit

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

Questions -

1) detectChanges() de détecter des changements seulement pour ses propres composants ou cela est-il également exécuter la détection de changement sur des composants enfant?

2) de la zone.lancer () déclencher la détection de changement de tous les composants de la racine jusqu'à la feuille?

dans la zone.run () et detectChanges () je suis curieux Quel est le meilleur dans performance ?

15
demandé sur Kim Kern 2017-03-23 12:24:11

2 réponses

ApplicationRef.tick (identique à setTimeout() ), et zone.run() cause la détection de changement sur l'ensemble de l'application. De plus, les écouteurs d'événements ajoutés à L'intérieur D'un angle ou par un angle (en utilisant des fixations de vue ou @HostBinding() ) provoquent une détection de changement pour l'ensemble de l'application.

ChangeDetectorRef.detectChanges exécute la détection de changement pour un composant spécifique (et ses descendants s'il y a lieu, par exemple en raison de liaisons d'entrée)

si un code courant à L'extérieur de la zone D'Angulars appelle dans le code anguleux et change l'état, puis la détection de changement doit être invoquée explicitement parce que L'angulaire n'a aucun moyen de savoir que l'État a changé.

si le changement d'état est local à un composant (par exemple un champ composants), ChangeDetectorRef.detectChanges ou ChangeDetectorRef.markforCheck sont plus efficaces.

si l'appel de l'extérieur par exemple navigue vers une autre route, cela peut avoir des conséquences sur un certain nombre de composants, et il n'est pas non plus clair lorsque tout le changement de route est terminé parce qu'il pourrait causer des appels asynchrones (et des callbacks étant appelés). Dans ce cas zone.run() est la meilleure option, parce que le code directement et indirectement invokedd (comme les callbacks des observables et des promesses) invoqué s'exécutera à L'intérieur de la zone angulaires et Angular les reconnaîtra et appellera la détection de changement automatiquement.

17
répondu Günter Zöchbauer 2017-03-23 09:50:45

les Deux sont des choses totalement différentes.

NgZone est une lib qui fournit des zones pour votre application de sorte que vous pouvez exécuter les instances dans plusieurs portées.

ChangeDetection est toujours de parent à la feuille comme A > B > C Lorsque vous appelez detectChanges (), il appellera aussi le composant courant et ses composants enfants. C'est donc la meilleure approche pour utiliser la stratégie OnPush changesdetectionStrategy pour les composants leaf, de sorte qu'ils ne détecteront les modificationsque lorsque les entrées sont mettre.

aussi, ApplicationRef est similaire à ChangeDetector; la différence est qu'il détectera les changements de la composante racine à la dernière composante enfant.

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

5
répondu Babar Bilal 2017-08-17 17:19:40