2013-09-02 15 views
6

ho una molto semplice configurazione app angolare, codice come segue:funzione di controller sempre chiamato due volte utilizzando ng presentazione

index.html

<!DOCTYPE html> 
<html> 
    <head> 
    <script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js'></script> 
    <script src='app.js'></script> 
    </head> 
    <body ng-app="app"> 
    <div ng-controller="MyCtrl"> 
     <div ng-show="ready()"> 
     Some content 
     </div> 
    </div> 
    </body> 
</html> 

E app.js

var app = angular.module('app', []); 

app.controller('MyCtrl', function($scope) { 
    console.log("MyCtrl called") 
    $scope.ready = function() { 
    console.log("ready called"); 
    return true; 
    } 
}) 

Se si esegue questa operazione con la console aperta, vedrai MyCtrl chiamato una volta e pronto chiamato due volte. Ho passato ore a cercare di capirlo, non vedo alcun motivo per cui lo $scope.ready verrebbe chiamato ma una sola volta.

Se si utilizza un v1.1.5 angolare e utilizzare ng-if invece di ng-show si avrà lo stesso comportamento, ma se si utilizza ng-init si chiama correttamente $scope.ready una sola volta. Nel mio caso ho bisogno di ng-show o ng-if.

Plunkr: http://plnkr.co/edit/ZSwVNLeFSuhbouXZu9SM?p=preview

Chiarimento: di elaborare su quello che sto puntando, diciamo $scope.ready ad un certo punto torna a fine false (forse fa una chiamata AJAX, che non dovrebbe essere chiamato più di una volta), vorrei che "Alcuni contenuti" non siano più visibili. Cioè, comportamento dinamico basato sul risultato di $scope.ready.

Qualche idea? Grazie per l'aiuto!

Per il record this e this non sono lo stesso problema.

+1

'ng-init' viene chiamato nella fase' $ compile', chiamata solo una volta. Tutto il resto è chiamato nel ciclo '$ digest', che viene sempre chiamato due volte (anche se non ho mai capito perché). –

+0

Cosa mi consigliate allora? Per espandere la mia domanda, quando ad un certo punto '$ scope.ready' restituisce' false' (diciamo che la funzione chiama un'altra funzione), vorrei che "alcuni contenuti" non siano più visibili. Per esempio. comportamento dinamico Grazie – MusikAnimal

+1

Angular sta usando "dirty checking" per vedere se il risultato della tua funzione $ scope è cambiato. Questa è una buona lettura: http://hueypetersen.com/posts/2013/06/17/angular_is_slow/. –

risposta

3

C'era un bug report su questo, e la risposta è stata qualcosa a che fare con il compilatore facendo un doppio controllo

Questo è il comportamento previsto. AngularJS esegue la chiamata due volte per assicurarsi che il modello si sia stabilizzato prima di renderlo.

Non ci dovrebbero essere ulteriori informazioni sul motivo per cui questo è qui http://docs.angularjs.org/guide/compiler

Bug Report: https://github.com/angular/angular.js/issues/1146

+0

Questo non è un bug né ha nulla a che fare con il compilatore AngularJS. Ecco perché il problema di Github è stato chiuso. –

+0

Non ho mai detto che si trattasse di un bug e hanno consigliato di controllare i documenti per il compilatore per ulteriori informazioni. – iConnor

+1

Non sto scrivendo il commento per te in modo specifico, sto commentando per coloro che potrebbero leggere la tua risposta e avere l'idea sbagliata che questo è un problema causato da "il compilatore che esegue un doppio controllo" (che è completamente scorretto). –

13

Ciò è di progettazione, non è un errore (e non ha nulla a che fare con la Compilatore AngularJS, come un'altra risposta erroneamente dichiarata). ng-show e ng-hide funzionano "guardando" i cambiamenti dell'espressione ready().

Ad ogni ciclo di digerire, per ogni orologio, AngularJS valuta l'espressione associata per vedere se c'è qualche cambiamento e se c'è, invocando l'ascoltatore (nel caso di ng-show/ng-hide, l'ascoltatore mostrare o nascondere l'elemento di base sul valore restituito da ready()).

Ora, AngularJS non può essere solo soddisfatti del primo valore restituito da ready() perché durante lo stesso ciclo di digerire, qualcosa (ad esempio, un'altra espressione orologio) potrebbe effettivamente fare qualche cambiamento che provoca tutto quello restituito dal ready() ad essere un valore diverso (es. modificando una variabile isReady che viene restituita da ready()). Ovviamente, gli sviluppatori si aspetterebbero che l'ultimo valore si rifletta sul DOM.

Pertanto, AngularJS valuterà ogni espressione dell'orologio almeno una volta per assicurarsi che sia "stabilizzato" prima di terminare un ciclo di digestione. Naturalmente, questo può portare a infinite iterazioni di digestione se un'espressione continua a cambiare, quindi AngularJS genererà un errore se un ciclo di digest non può finire entro 10 iterazioni.

+1

inviando questo valore in modo che le persone non saltino questa risposta. –

Problemi correlati