Quelle est la différence entre markForCheck () et detectChanges ()

Quelle est la différence entre ChangeDetectorRef.markForCheck() et ChangeDetectorRef.detectChanges() ?

Je n’ai trouvé des informations sur SO que sur la différence entre NgZone.run() , mais pas entre ces deux fonctions.

Pour des réponses ne faisant référence qu’à la doc, veuillez illustrer certains scénarios pratiques pour choisir l’un par rapport à l’autre.

    De docs:

    detectChanges (): vide

    Vérifie le détecteur de changement et ses enfants.

    Cela signifie que si quelque chose à l’intérieur de votre modèle (votre classe) a changé mais qu’il n’a pas reflété la vue, vous devrez peut-être notifier Angular pour détecter ces modifications (détecter les modifications locales) et mettre à jour la vue.

    Les scénarios possibles pourraient être:

    1- Le détecteur de changement est détaché de la vue (voir détachement )

    2- Une mise à jour a eu lieu mais elle n’a pas été dans la zone angular, donc Angular ne le sait pas.

    Comme quand une fonction tierce a mis à jour votre modèle et que vous souhaitez mettre à jour la vue par la suite.

      someFunctionThatIsRunByAThirdPartyCode(){ yourModel.text = "new text"; } 

    Comme ce code est en dehors de la zone Angular (probablement), vous devez probablement vous assurer de détecter les modifications et de mettre à jour la vue, donc:

      myFunction(){ someFunctionThatIsRunByAThirdPartyCode(); // Let's detect the changes that above function made to the model which Angular is not aware of. this.cd.detectChanges(); } 

    NOTE :

    Il y a d’autres façons de faire ce travail, en d’autres termes, il y a d’autres façons d’apporter ce changement au cycle de changement angular.

    ** Vous pouvez envelopper cette fonction tierce dans une zone.run:

      myFunction(){ this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode); } 

    ** Vous pouvez envelopper la fonction dans un setTimeout:

     myFunction(){ setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0); } 

    3- Il existe également des cas où vous mettez à jour le modèle une fois le change detection cycle terminé. Dans ce cas, vous obtenez cette erreur redoutée:

    “L’expression a changé après avoir été vérifiée”;

    Cela signifie généralement (du langage Angular2):

    J’ai vu un changement dans votre modèle causé par l’un de mes moyens acceptés (événements, requêtes XHR, setTimeout et …), puis j’ai exécuté ma détection de modifications pour mettre à jour votre vue et je l’ai finie. Fonctionne dans ton code qui remet à jour le modèle et je ne veux plus exécuter ma détection de changement car il n’y a plus de vérification sale comme AngularJS: D et nous devrions utiliser un stream de données à sens unique!

    Vous allez certainement rencontrer cette erreur: P.

    Deux façons de résoudre ce problème:

    1- Bien : assurez-vous que la mise à jour est dans le cycle de détection des modifications (les mises à jour Angular2 sont un stream unique qui ne se produit qu’une fois, ne mettez pas le modèle à jour et déplacez votre code vers un meilleur endroit).

    2- Paresseux: lancez detectChanges () après cette mise à jour pour rendre angular2 heureux, ce n’est certainement pas le meilleur moyen, mais comme vous avez demandé quels sont les scénarios possibles, c’est l’un d’entre eux.

    De cette façon, vous dites: Je sais sincèrement que vous avez effectué la détection des modifications, mais je veux que vous le fassiez à nouveau car je devais mettre à jour quelque chose à la fin de la vérification.

    3- Placez le code dans un setTimeout , car setTimeout est corrigé par zone et exécutera detectChanges après sa fin.


    De la documentation

     markForCheck() : void 

    Marque tous les ancêtres ChangeDetectionStrategy à vérifier.

    Cela est surtout nécessaire lorsque la stratégie ChangeDetectionStrategy de votre composant est OnPush .

    OnPush lui-même signifie que seule la détection des modifications est exécutée:

    1- L’un des @inputs du composant a été complètement remplacé par une nouvelle valeur, ou simplement mis, si la référence de la propriété @Input a complètement changé.

    Donc, si ChangeDetectionStrategy de votre composant est OnPush et que vous avez alors:

      var obj = { name:'Milad' }; 

    Et puis vous le mettez à jour / modifiez comme:

      obj.name = "a new name"; 

    Cela ne mettra pas à jour la référence obj , par conséquent, la détection des modifications ne sera pas exécutée. La vue ne reflète donc pas la mise à jour / la mutation.

    Dans ce cas, vous devez indiquer manuellement à Angular de vérifier et de mettre à jour la vue (markForCheck);

    Donc, si vous avez fait ceci:

      obj.name = "a new name"; 

    Vous devez faire ceci:

      this.cd.markForCheck(); 

    Au lieu de cela, une détection de changement s’exécuterait:

      obj = { name:"a new name" }; 

    Qui a complètement remplacé le précédent obj par un nouveau {} ;

    2- Un événement a été déclenché, comme un clic ou quelque chose comme cela ou tout composant enfant a émis un événement.

    Des événements comme:

    • Cliquez sur
    • Keyup
    • Événements d’abonnement
    • etc.

    Donc en bref:

    • Utilisez la detectChanges() lorsque vous avez mis à jour le modèle après que le detectChanges() angular a été exécuté, la détection des modifications, ou si la mise à jour n’a jamais été dans un monde angular.

    • Utilisez markForCheck() si vous utilisez OnPush et que vous ChangeDetectionStrategy le ChangeDetectionStrategy en mutant certaines données ou que vous avez mis à jour le modèle dans un setTimeout ;

    La plus grande différence entre les deux est que detectChanges() déclenche réellement la détection des modifications, alors que markForCheck() ne déclenche pas la détection des modifications.

    DétecterChangements

    Celui-ci est utilisé pour exécuter la détection des modifications pour l’arborescence des composants en commençant par le composant que vous déclenchez detectChanges() . La détection des modifications sera donc exécutée pour le composant actuel et tous ses enfants. Angular contient des références à l’arborescence du composant racine dans ApplicationRef et lorsqu’une opération asynchrone se produit, elle déclenche la détection des modifications sur ce composant racine via une méthode wrapper tick() :

     @Injectable() export class ApplicationRef_ extends ApplicationRef { ... tick(): void { if (this._runningTick) { throw new Error('ApplicationRef.tick is called recursively'); } const scope = ApplicationRef_._tickScope(); try { this._runningTick = true; this._views.forEach((view) => view.detectChanges()); <------------------ 

    view ici est la vue du composant racine. Il peut exister de nombreux composants racine, comme je l'ai décrit dans la section Quelles sont les implications de l'amorçage de plusieurs composants .

    @milad a décrit les raisons pour lesquelles vous pourriez potentiellement avoir besoin de déclencher une détection de changement manuellement.

    markForCheck

    Comme je le disais, ce type ne déclenche aucune détection de changement. Il monte simplement du composant actuel vers le composant racine et met à jour son état d' ChecksEnabled à ChecksEnabled . Voici le code source:

     export function markParentViewsForCheck(view: ViewData) { let currView: ViewData|null = view; while (currView) { if (currView.def.flags & ViewFlags.OnPush) { currView.state |= ViewState.ChecksEnabled; <----------------- } currView = currView.viewContainerParent || currView.parent; } } 

    La détection de modification réelle pour le composant n'est pas planifiée, mais lorsque cela se produira dans le futur (soit dans le cycle CD actuel ou suivant), les vues du composant parent seront vérifiées même si elles avaient des détecteurs de changement détachés. Les détecteurs de modifications peuvent être détachés à l'aide de cd.detach() ou en spécifiant la stratégie de détection des modifications OnPush . Tous les gestionnaires d'événements natifs marquent toutes les vues de composant parent pour vérification.

    Cette approche est souvent utilisée dans le ngDoCheck cycle de vie ngDoCheck . Si vous pensez que ngDoCheck signifie que votre composant est en cours de vérification, lisez cet article .

    Voir aussi Tout ce que vous devez savoir sur la détection des modifications dans Angular pour plus de détails.