8 votes

La détection des changements ne se déclenche pas dans le délai d'attente avec ChangeDetectionStrategy.OnPush.

J'ai deux composants, où j'utilise ChangeDetectionStrategy.OnPush. Un composant parent :

@Component({
 changeStaregy: ChangeDetectionStrategy.OnPush,
 template:`
    <button (click)="onClick()">clear</button>
    <div>
        <test [model]="model"></test>
    </div>`
})
export class AppComponent {
    model: TestModel;

    constructor(){
      this.model = { id: 1, text: 'bla bla bla'}
    }

    onClick() {
      this.model = new TestModel();
    }
}

et un composant enfant qui affiche simplement une donnée :

@Component({
   changeStrategy: ChangeDetectionStrategy.OnPush,
   selector: 'test',
   template: `
    <div>
          <div> {{model.id}} </div>
           <div> {{model.text}} </div>
    </div>`
})

export class TestComponent {
   @Input() model: TestModel;

}

Lorsque je clique sur le bouton "clear", il appelle la fonction onClick(), qui attribue une entité vide à "model". Cela déclenche une détection de changement, car l'entrée a été modifiée (stratégie OnPush). Mais si j'enveloppe l'affectation avec un appel asynchrone, la détection de changement ne fonctionne pas et l'interface utilisateur n'est donc pas mise à jour :

onClick() {
  setTimeout(() => {
    this.model = new TestModel();
  }, 2000);
}

Angular2+ dispose de NgZone qui corrige une fonction setTimeout. Le setTimeout patché doit déclencher la détection de changement, mais dans mon cas, il ne le fait pas. Pourquoi la détection de changement ne fonctionne pas ? Comment puis-je le corriger ?

5voto

PierreDuc Points 25962

Parce que le changeDetectionStrategy est réglé sur OnPush sur le parent, le cycle de détection des changements s'arrête à l'élément parent. En conséquence, tout enfant de ce parent aura la stratégie définie sur OnPush indépendamment de son propre réglage.

Non @Input du parent change, et donc le détecteur de changement ne va pas plus loin vers les enfants du parent. Vous devriez exécuter un detectChanges pour que les changements prennent effet

1voto

alt255 Points 771

Lorsque vous utilisez la stratégie de détection des modifications OnPush, la détection des modifications s'effectue uniquement lorsqu'une propriété d'entrée change, lorsque l'événement lié est déclenché par le composant ou lorsque vous détectez manuellement les modifications.

Dans votre exemple plunker, le composant enfant modifie l'entrée par lui-même en changeSetTimeout y changeModelInZone .

Lorsque vous cliquez sur le bouton, un deuxième événement limité dans le temps est déclenché, ce qui entraîne la mise à jour du modèle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X