2016-06-09 10 views
9

Sto avendo qualche strano problema con ng-class, e sospetto che abbia a che fare con le condizioni di gara.Condizioni di gara con ng-class e animazione

Ecco plunker example

Ecco il relativo codice js

self.slideLeft = function() { 
     if (self.end_index < self.list_of_stuff.length) { 
      self.direction = 'left'; 

      debugger; 
      self.start_index = self.start_index + 4; 
      self.end_index = self.end_index + 4; 
      self.display_list = self.list_of_stuff.slice(self.start_index, self.end_index);    
     } 

    } 

    self.slideRight = function() { 
     if (self.start_index > 0) { 
      self.direction = 'right'; 
      debugger; 

      self.start_index = self.start_index - 4; 
      self.end_index = self.end_index - 4; 
      self.display_list = self.list_of_stuff.slice(self.start_index, self.end_index);    
     } 
    } 

Ecco l'rilevante html

<div class="stuff-wrapper"> 
    <div class="stuff" 
     ng-class="bCtrl.directionClass()" 
     ng-repeat="stuff in bCtrl.display_list"> 
     {{stuff}} 
    </div> 
    </div> 

Ecco l'animazione.

.left.ng-enter, 
.left.ng-leave { 
    -webkit-transition: all 1s ease-in-out; 

} 

.left.ng-enter { 
    transition-delay: 0.7s; 
    opacity: 0; 
    left: 10%; 
} 
.left.ng-enter-active { 
    opacity: 1; 
    left: 0; 
} 

.left.ng-leave { 
    opacity: 1; 
    left: -10%; 
} 
.left.ng-leave-active { 
    left: -20%; 
    opacity: 0; 
} 

Questa è una semplice applicazione che fa scorrere un elenco di numeri a sinistra ea destra.

Se si preme il pulsante sinistro, i numeri scorrono verso sinistra.

Se si preme il pulsante destro, i numeri scorrono verso destra.

Ma vediamo che se c'è un cambio di direzione, il numero scorrerà prima nella direzione sbagliata, e la direzione successiva sarà corretta.

Ho il sospetto che ciò sia dovuto alle condizioni della gara.

Infatti, vedo che ng-class non viene applicato subito dopo aver modificato la direzione self.direction utilizzando il debugger.

Questo è molto curioso.

C'è un modo per combattere questo?

risposta

6

citare la risposta da questo (https://stackoverflow.com/a/21664152/2402929) domanda:

è necessario effettuare le modifiche ai $ scope.elements dopo il css classe viene aggiornato al DOM. Quindi è necessario ritardare la manipolazione del DOM per un ciclo di digest. Questo può essere fatto dal servizio di $ timeout (si prega di vedere questa risposta per ulteriori informazioni AngularJS $ evalAsync vs $ timeout):

I suoi elementi vengono rimossi nello stesso ciclo digerire come si sta aggiornando il css classi. Significato: il css non viene aggiornato e gli elementi vengono semplicemente rimossi.

Il ciclo digest comprenderà l'intera funzione ng-clic, poiché con tutte le direttive angolari incorporate il codice è racchiuso all'interno di $ scope. $ Apply call.

Per chiarire:.

$ portata $ applica() prende una funzione o una stringa di espressione angolare, e lo esegue, quindi chiama $ portata $ digest() per modificare eventuali attacchi o osservatori. .

È possibile leggere ulteriori informazioni qui (http://jimhoskins.com/2012/12/17/angularjs-and-apply.html).

Così che cosa risolve il vostro problema è l'involucro la rimozione dei dati dal vostro array in un blocco di $ timeout, che ritarderà la manipolazione del DOM per un digerire ciclo e separare il cambio delle classi e la rimozione dei dati:

self.slideLeft = function() { 
      if (self.end_index < self.list_of_stuff.length) { 
       self.direction = 'left'; 

       self.start_index = self.start_index + 4; 
       self.end_index = self.end_index + 4; 
       $timeout(function(){ 
       self.display_list = self.list_of_stuff.slice(self.start_index, self.end_index);    
       }); 
      } 

     } 

     self.slideRight = function() { 
      if (self.start_index > 0) { 
       self.direction = 'right'; 

       self.start_index = self.start_index - 4; 
       self.end_index = self.end_index - 4; 
       $timeout(function(){ 
       self.display_list = self.list_of_stuff.slice(self.start_index, self.end_index);    
       }); 
      } 
     } 

Ed ecco un plunker di lavoro: http://plnkr.co/edit/30wJhL?p=preview