Cet excellent article Si vous pensez que ngDoCheck
signifie que votre composant est en cours de vérification lire cet article explique l'erreur en profondeur.
Le contenu de cette réponse est fondée sur l'angle de la version 2.x.x. Pour la plus récente version 4.x.x voir ce post.
Il n'y a rien sur internet sur le fonctionnement interne de détection de changement, donc j'ai dû passer environ une semaine de débogage sources, de sorte que cette réponse sera assez technique sur les détails.
Angulaire de l'application est un arbre de vues (AppView
de la classe qui s'est étendu par la Composante spécifique de la classe générée par le compilateur). Chaque point de vue a une détection de changement de mode de vie en cdMode
de la propriété. La valeur par défaut de cdMode
est ChangeDetectorStatus.CheckAlways
, ce qui est cdMode = 2
.
Lors d'un changement de cycle de détection exécution, chaque parent vue vérifie si il doit effectuer la détection de changement sur l'enfant de voir ici:
detectChanges(throwOnChange: boolean): void {
const s = _scope_check(this.clazz);
if (this.cdMode === ChangeDetectorStatus.Checked ||
this.cdMode === ChangeDetectorStatus.Errored)
return;
if (this.cdMode === ChangeDetectorStatus.Destroyed) {
this.throwDestroyedError('detectChanges');
}
this.detectChangesInternal(throwOnChange); <---- performs CD on child view
où this
de points à l' child
vue. Donc, si cdMode
est ChangeDetectorStatus.Checked=1
, la détection de changement est ignorée pour les enfants immédiats et tous ses descendants à cause de cette ligne.
if (this.cdMode === ChangeDetectorStatus.Checked ||
this.cdMode === ChangeDetectorStatus.Errored)
return;
Ce changeDetection: ChangeDetectionStrategy.OnPush
n'est tout simplement fixe cdMode
de ChangeDetectorStatus.CheckOnce = 0
, donc après la première exécution de détection de changement de la vue enfant aura son cdMode
ensemble de ChangeDetectorStatus.Checked = 1
en raison de ce code:
if (this.cdMode === ChangeDetectorStatus.CheckOnce)
this.cdMode = ChangeDetectorStatus.Checked;
Ce qui signifie que la prochaine fois qu'un changement de cycle de détection commence il n'y aura pas de changement de détection effectuée pour la vue enfant.
Il y a quelques options sur la manière d'exécuter la détection de changement de ce point de vue. La première est de changer l'enfant de la vue d' cdMode
de ChangeDetectorStatus.CheckOnce
, ce qui peut être fait en utilisant this._changeRef.markForCheck()
en ngDoCheck
du cycle de vie de crochet:
constructor(private _changeRef: ChangeDetectorRef) { }
ngDoCheck() {
this._changeRef.markForCheck();
}
Il suffit simplement de change cdMode
de la vue actuelle et de ses parents de ChangeDetectorStatus.CheckOnce
, alors la prochaine fois que le changement de la détection est effectuée à l'affichage actuel est cochée.
Vérifier un exemple complet d' ici, dans les sources, mais voici l'essentiel:
constructor(ref: ChangeDetectorRef) {
setInterval(() => {
this.numberOfTicks ++
// the following is required, otherwise the view will not be updated
this.ref.markForCheck();
^^^^^^^^^^^^^^^^^^^^^^^^
}, 1000);
}
La deuxième option est de les appeler detectChanges
sur la vue elle-même qui va exécuter la détection de changement sur la vue actuelle si cdMode
n'est ChangeDetectorStatus.Checked
ou ChangeDetectorStatus.Errored
. Depuis, onPush
angulaire ensembles cdMode
de ChangeDetectorStatus.CheckOnce
, angulaire va exécuter la détection de changement.
Donc, ngDoCheck
ne modifie pas le changement de détection, il est simplement appelé à chaque changé de détection de cycle et c'est le seul travail est de définir la vue actuelle cdMode
comme checkOnce
, de sorte que lors de la prochaine détection de changement de cycle, il est vérifié pour les modifications. Voir cette réponse pour plus de détails. Si le point de vue actuel de la détection de changement de mode est - checkAlways
(activée par défaut si onPush stratégie n'est pas utilisé), ngDoCheck
semblent être d'aucune utilité.