2014-10-31 25 views
6

Verbrauch:AngularJS überschreibt isoliert Richtlinie Anwendungsbereich

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

Richtlinie:

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; 
    } 
]); 

Konsolenausgabe

"true" 
"false" 
"true" 

Was genau ist hier passiert? Die Variable wird als String übergeben ("true"), ich ändere sie, dann wird sie wieder ersetzt? Ich möchte den Zyklus hier verstehen. Liegt das daran, dass ein zusätzlicher Kompilierungs- oder Digest-Zyklus auftritt und alle isolierten Bereichswerte erneut berechnet werden? Ich dachte, dass, einmal gesetzt, Variablen wie folgt (@, nur String in Direktive) bleiben die gleichen?

Gibt es eine Möglichkeit, innerhalb der Direktive zu einem Zeitpunkt zu verbinden, nach dem Zeichenfolge Variablen nicht ersetzt werden, oder wird es immer so mit jedem Digest oder whatnot arbeiten, und ich bin gezwungen, $ watch zu verwenden?

+0

Dies ist mit ähnlichen Frage verwandt - http://stackoverflow.com/questions/22967024/initializing-isolated-scope-inside-a-directive, aber ich finde nicht die ursprüngliche Antwort zu vervollständigen, weil ich verwende eval, um diese Zeichenfolge in boolesche Werte neu zu bewerten, möchten ihren Wert nicht wirklich ändern, sondern dafür sorgen, dass sie boolesch bleiben. Also übersetze ich eins in boolean und dann wird es wieder überschrieben. – rattkin

Antwort

7

@ bindet den übergeordneten Bereich an den isolierten Bereich, und es ist eine einseitige (nicht einmalige) Bindung. Wenn der äußere Gültigkeitsbereich geändert wird, wird der Wert im isolierenden Gültigkeitsbereich der Richtlinie zurückgesetzt.

Under the covers, Angular ruft attrs.$observe auf dem Elementattribut mit "@" auf. Dies bedeutet, dass eine Beobachterfunktion für den nächsten $ Digest-Zyklus nach der Kompilierung in die Warteschlange gestellt wird. Diese Beobachterfunktion setzt die Gültigkeitsbereichsvariable jedes Mal, wenn sich der dem Attribut zugewiesene interpolierte Wert ändert.

Also, die High-Level-Schritte sind:

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 

dies also gegeben, können Sie jetzt sehen, warum Ihre Änderung bestehen nicht. Es würde, wenn Sie es nach all diesen Schritten gemacht haben - d. H. Mit einer Zeitüberschreitung oder als Reaktion auf ein Ereignis. Und nur, wenn der interpolierte Attributwert nicht geändert wurde.

Dies ist nicht so mit "=".

Hier ist eine plunker, die die Unterschiede veranschaulicht.

Wenn Sie eine einmalige Passage von Variablen wollen, setzen Sie einfach den Umfang Variable ein Attribut in der Link-Funktion oder den Controller

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

und entfernen myVar vom Anwendungsbereich.

+0

Wonach suchen Sie noch? Es beantwortet deine Frage. Warum ändert es sich? - weil es eine unidirektionale Bindung ist, d. h. jede Änderung in der übergeordneten Bereichsvariable wird eine Änderung in der Bereichsvariablen des gebundenen Isolats verursachen. In Ihrer Frage haben Sie eine falsche Annahme gemacht, dass dies nicht der Fall ist. –

+0

Ich weiß, dass es eine Bindung gibt. Was ich nicht weiß (und wissen will), was genau die Auswertungszyklusneuauswertung auslöst, so dass es neues Objekt wieder auffüllt, auch wenn es vorher schon einmal geschehen ist und sein Wert sich nicht geändert hat. Das sind tiefe innere Dinge. – rattkin

+0

$ Digest-Zyklus wird gestartet, wenn eine Komponente '$ scope. $ Apply' aufruft. Es geht auch beim ersten Lauf in die Hierarchie ein. Wenn Sie über die Bindung wissen, wissen Sie, dass dies mit der Dirty-Prüfung geschieht - weil Sie den Wert zwischen den Läufen geändert haben, in denen die Bindung erneut angewendet wurde. Siehe meine eigene Frage und die [Antwort] (http://stackoverflow.com/a/25908745/968155) –

Verwandte Themen