2014-10-31 10 views
6

Usage:AngularJS sovrascrive isolato direttiva portata

<my-directive my-var="true"></my-directive> 

direttiva:

app.directive('myDirective', [ 
    function() { 
     var definition = { 
      restrict: "E", 
      replace: false, 
      transclude: false, 
      scope: { 
       myVar: '@', 
      }, 
      controller: ['$scope', function($scope) { 
       console.log($scope.myVar); // "true" 
       $scope.myVar = "false"; 
       console.log($scope.myVar); // "false" 

       setTimeout(function() { 
        console.log($scope.myVar); // "true" (!) 
       }, 100); 
      }] 
     }; 

     return definition; 
    } 
]); 

uscita Console

"true" 
"false" 
"true" 

Quello che sta accadendo proprio qui? La variabile viene passata come stringa ("true"), la sto cambiando, quindi viene sostituita di nuovo? Mi piacerebbe capire il ciclo qui. Ciò è dovuto al fatto che è necessario eseguire un ciclo di compilazione o digest aggiuntivo e ricalcolare di nuovo tutti i valori degli ambiti isolati? Ho pensato che una volta impostato, le variabili passate in questo modo (@, solo la stringa nella direttiva) rimarrebbero le stesse?

C'è un modo per collegarsi alla direttiva in un momento, dopo di che le variabili di stringa non vengono sostituite, o funzionerà sempre così con ogni digest o quant'altro, e sono obbligato a usare $ watch?

+0

Questo è correlato a una domanda simile - http://stackoverflow.com/questions/22967024/initializing-isolated-scope-inside-a-directive, ma non trovo la risposta originale per essere completa, perché io uso eval per rivalutare queste stringhe in booleani, non voglio davvero cambiare il loro valore, ma per farli rimanere booleani. Quindi traduco uno in booleano, e poi viene cancellato nuovamente. – rattkin

risposta

7

@ associa l'ambito padre all'ambito isolato ed è un'associazione unidirezionale (non una tantum). Pertanto, qualsiasi modifica dell'ambito esterno reimposterà il valore nell'ambito dell'isolamento della direttiva.

Under the covers, chiamate angolari attrs.$observe sull'attributo elemento con "@". Ciò che fa è l'accodamento di una funzione di osservatore per il successivo ciclo digest di $ dopo la compilazione. Questa funzione dell'osservatore è ciò che imposta la variabile scope ogni volta che c'è una variazione nel valore interpolato assegnato all'attributo.

Così, i passaggi ad alto livello sono:

1) for `@` scope variable, set an observer function and queue it for later 
2) set `@` scope variable to the interpolated value 
3) run the controller, pre- and post-link functions 
... 
N) observer runs against interpolated value and sets the scope value 

Quindi, dato questo, è ora possibile vedere perché la modifica non persistono. Lo farebbe, se lo avessi fatto dopo tutti questi passaggi - cioè con un timeout o in risposta a un evento. E solo se il valore interpolato dell'attributo non è cambiato.

Questo NON è vero con "=".

Ecco un plunker che illustra le differenze.

Se si desidera un passaggio di una volta di variabili, basta impostare la variabile di ambito utilizzando un attributo nella funzione di collegamento o il controller

scope.myVar = $attrs["my-var"]; 

e rimuovere myVar dal campo di applicazione.

+0

Cos'altro stai cercando? Risponde alla tua domanda. Perché cambia? - poiché si tratta di un legame unidirezionale, ovvero qualsiasi modifica nella variabile dell'ambito genitore causerà una modifica nella variabile dell'ambito dell'isolamento associato. Nella tua domanda hai fatto un'ipotesi errata che non lo sarebbe. –

+0

So che c'è un legame stabilito. Quello che non so (e voglio sapere), che cosa fa esattamente innescare la rivalutazione del ciclo di digest, così che popola di nuovo il nuovo oggetto, anche se ha fatto prima e il suo valore non è cambiato. Queste sono una specie di cose interne profonde. – rattkin

+0

Il ciclo digest di $ viene avviato ogni volta che un componente chiama '$ scope. $ Apply'. Va anche su e giù per la gerarchia alla prima esecuzione. Se sai di legare, sai che è fatto usando il controllo sporco - perché hai cambiato il valore tra le esecuzioni ha riapplicato l'associazione. Vedi la mia domanda e la [risposta] (http://stackoverflow.com/a/25908745/968155) –