Was ist der Unterschied zwischen '@' und '=' im Richtlinienumfang in AngularJS?

1067

Ich habe die AngularJS- Dokumentation zu diesem Thema sorgfältig gelesen und dann mit einer Anweisung herumgespielt. Hier ist die Geige .

Und hier sind einige relevante Ausschnitte:

  • Aus dem HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • Aus der Fensterrichtlinie:

    scope: { biTitle: '=', title: '@', bar: '=' },

Es gibt einige Dinge, die ich nicht verstehe:

  • Warum muss ich "{{title}}"mit '@'und "title"mit verwenden '='?
  • Kann ich auch direkt auf den übergeordneten Bereich zugreifen, ohne mein Element mit einem Attribut zu dekorieren?
  • In der Dokumentation heißt es : "Oft ist es wünschenswert, Daten aus dem isolierten Bereich per Ausdruck an den übergeordneten Bereich zu übergeben." Dies scheint jedoch auch bei bidirektionaler Bindung gut zu funktionieren. Warum sollte die Ausdrucksroute besser sein?

Ich habe eine andere Geige gefunden, die auch die Ausdruckslösung zeigt: http://jsfiddle.net/maxisam/QrCXh/

iwein
quelle
18
Gutes Argument. Die Fähigkeit zu recherchieren und Antworten zu finden ist wichtig.
Jonathan
1
Mit einfachen Worten, =wird im Direktiven-Isolationsbereich verwendet, um eine bidirektionale Bindung zu ermöglichen, und @aktualisiert nicht das Modell, sondern nur die Richtlinienbereichswerte.
Stahl
@iwein warum funktioniert Ihr Geigencode unter jsfiddle.net/maxisam/QrCXh nicht mit googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Ihr Code funktioniert nur, wenn ich Ihre cdn
code.angularjs.org/1.0.1/angular-1.0.1.js
Ich sehe unten viele gute Antworten, aber kann jemand einen Hinweis auf die offizielle eckige Dokumentation geben, die diese Frage beantwortet?
John Henckel

Antworten:

1151

Warum muss ich "{{title}}" mit ' @ ' und "title" mit ' = ' verwenden?

@ bindet eine Eigenschaft local / directive scope an den ausgewerteten Wert des DOM-Attributs . Wenn Sie title=title1oder verwenden title="title1", ist der Wert des DOM-Attributs "title" einfach die Zeichenfolge title1. Wenn Sie verwenden title="{{title}}", ist der Wert des DOM-Attributs "title" der interpolierte Wert von {{title}}, daher entspricht die Zeichenfolge der übergeordneten Bereichseigenschaft "title", auf die derzeit festgelegt ist. Da Attributwerte immer Zeichenfolgen sind, erhalten Sie bei Verwendung von @ immer einen Zeichenfolgenwert für diese Eigenschaft im Gültigkeitsbereich der Direktive .

= bindet eine lokale / direktive Bereichseigenschaft an eine übergeordnete Bereichseigenschaft . Mit = verwenden Sie also den Namen der übergeordneten Modell- / Bereichseigenschaft als Wert des DOM-Attributs. Sie können {{}}s nicht mit = verwenden .

Mit @ können Sie Dinge tun wie title="{{title}} and then some"- {{title}} wird interpoliert, dann wird die Zeichenfolge "und einige davon" damit verkettet. Die letzte verkettete Zeichenfolge wird von der Eigenschaft local / directive scope abgerufen. (Sie können dies nicht mit = , nur @ tun .)

Mit @ müssen Sie verwenden, attr.$observe('title', function(value) { ... })wenn Sie den Wert in Ihrer Verknüpfungsfunktion verwenden müssen. ZB if(scope.title == "...")funktioniert nicht wie erwartet. Beachten Sie, dass Sie nur asynchron auf dieses Attribut zugreifen können . Sie müssen $ watch () nicht verwenden, wenn Sie nur den Wert in einer Vorlage verwenden. ZB , template: '<div>{{title}}</div>'.

Mit = müssen Sie $ watch nicht verwenden.

Kann ich auch direkt auf den übergeordneten Bereich zugreifen, ohne mein Element mit einem Attribut zu dekorieren?

Ja, aber nur, wenn Sie keinen isolierten Bereich verwenden. Entfernen Sie diese Zeile aus Ihrer Direktive

scope: { ... }

und dann wird Ihre Direktive keinen neuen Geltungsbereich erstellen. Es wird der übergeordnete Bereich verwendet. Sie können dann direkt auf alle übergeordneten Bereichseigenschaften zugreifen.

In der Dokumentation heißt es: "Oft ist es wünschenswert, Daten aus dem isolierten Bereich über einen Ausdruck an den übergeordneten Bereich zu übergeben." Dies scheint jedoch auch bei bidirektionaler Bindung gut zu funktionieren. Warum sollte die Ausdrucksroute besser sein?

Ja, durch bidirektionale Bindung können der lokale / Direktivenbereich und der übergeordnete Bereich Daten gemeinsam nutzen. Mit "Ausdrucksbindung" kann die Direktive einen Ausdruck (oder eine Funktion) aufrufen, der durch ein DOM-Attribut definiert ist. Außerdem können Sie Daten als Argumente an den Ausdruck oder die Funktion übergeben. Wenn Sie also keine Daten für das übergeordnete Element freigeben müssen - Sie möchten nur eine im übergeordneten Bereich definierte Funktion aufrufen -, können Sie die & -Syntax verwenden.

Siehe auch

Mark Rajcok
quelle
1
Huh, das ist ein wirklich seltsames Verhalten, besonders wenn keine Interpolation verwendet wird und nur versucht wird, eine Zeichenfolge zu übergeben. Anscheinend wurde die Pull-Anforderung tatsächlich in die Entwicklungs-Builds integriert und befindet sich in RC-Builds 1.1.5 und 1.2.0. Gut, dass sie dieses sehr unintuitive Verhalten behoben haben!
Ibrahim
50
Das Schreiben von '@' oder '=' ist so viel klarer als das Schreiben von "eval-dom" oder "parent-scope" oder einem anderen von Menschen lesbaren Text. Gute Designentscheidung.
Den
13
@('at') kopiert den Wert des 'ATtribute'. =('gleich') entspricht der Aussage, dass der Schlüssel Ihrem Ausdruck entspricht. Zumindest halte ich sie so auf der Straße.
Matt DeKrey
1
Sind Sie sicher, dass = nur für Eigenschaften des übergeordneten Bereichs gilt? Jeder Ausdruck scheint zu funktionieren - nicht nur die Eigenschaften des übergeordneten Bereichs.
Jonathan Aquino
4
@ JonathanAquino, ja das funktioniert, aber @ wäre besser geeignet - mit foo="{{1+1}}"- weil wir hier keine bidirektionale Datenbindung benötigen. Der Punkt, den ich im obigen Kommentar versucht habe, ist, dass wir = nur verwenden sollten, wenn die Direktive eine bidirektionale Datenbindung benötigt. Verwenden Sie @ oder & anderweitig.
Mark Rajcok
542

Es gibt viele gute Antworten hier, aber ich möchte meine Perspektive auf die Unterschiede zwischen bieten @, =und &Bindung , die für mich als nützlich erwiesen.

Alle drei Bindungen sind Möglichkeiten, Daten von Ihrem übergeordneten Bereich über die Attribute des Elements an den isolierten Bereich Ihrer Direktive zu übergeben:

  1. @ Bindung dient zum Übergeben von Zeichenfolgen. Diese Zeichenfolgen unterstützen {{}}Ausdrücke für interpolierte Werte. Beispielsweise: . Der interpolierte Ausdruck wird anhand des übergeordneten Gültigkeitsbereichs der Direktive ausgewertet.

  2. = Bindung ist für die bidirektionale Modellbindung. Das Modell im übergeordneten Bereich ist mit dem Modell im isolierten Bereich der Richtlinie verknüpft. Änderungen an einem Modell wirken sich auf das andere aus und umgekehrt.

  3. & Binding dient zum Übergeben einer Methode in den Geltungsbereich Ihrer Direktive, damit sie innerhalb Ihrer Direktive aufgerufen werden kann. Die Methode ist an den übergeordneten Gültigkeitsbereich der Direktive gebunden und unterstützt Argumente. Wenn die Methode beispielsweise im übergeordneten Bereich Hallo (Name) lautet, müssen Sie $ scope.hello ({name: 'world'}) aufrufen, um die Methode in Ihrer Direktive auszuführen.

Ich finde, dass es einfacher ist, sich an diese Unterschiede zu erinnern, wenn man sich durch eine kürzere Beschreibung auf die Bereichsbindungen bezieht:

  • @ Bindung von Attributzeichenfolgen
  • = Zweiwege-Modellbindung
  • & Bindung der Rückrufmethode

Die Symbole machen auch klarer, was die Bereichsvariable innerhalb der Implementierung Ihrer Direktive darstellt:

  • @ Zeichenfolge
  • = Modell-
  • & Methode

In der Reihenfolge der Nützlichkeit (für mich jedenfalls):

  1. =
  2. @
  3. &
Pixelbits
quelle
13
"&"Unterstützt tatsächlich Argumente (oder eher Einheimische) der Form : callback({foo: "some value"}), die dann verwendet werden könnten <my-dir callback="doSomething(foo)">. Ansonsten gute Antwort
New Dev
11
Sollte als Antwort akzeptiert werden. Hier ist ein kurzer Artikel mit den gleichen Informationen, aber mit zusätzlichen Codebeispielen: umur.io/…
Kevin
4
& ist NICHT "Callback-Methodenbindung", sondern Angular-Ausdrucksbindung. Ein besonderes, aber nicht das einzige Beispiel ist der Ausdruck callback(argument). Welches ist immer noch nicht das gleiche wie sich callbackselbst.
Dmitri Zaitsev
14
Obwohl ich es liebte, wie eindeutig die höherrangige Antwort war, fand ich, dass diese eine nützlichere Wirkung hatte, und nachdem ich diese gelesen hatte, verstand ich die vorherige Antwort viel besser.
Rbnzdave
1
Ich stimme dem obigen Kommentar zu, diese Antwort ist klarer, endgültiger und nützlicher für die Frage. Es wird so ausführlich erklärt, dass Sie die Informationen verwenden können.
user3125823
64

Das =bedeutet bidirektionale Bindung, also einen Verweis auf eine Variable zum übergeordneten Bereich. Das heißt, wenn Sie die Variable in der Direktive ändern, wird sie auch im übergeordneten Bereich geändert.

@ bedeutet, dass die Variable in die Direktive kopiert (geklont) wird.

Soweit ich weiß, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>sollte auch funktionieren. bi-titleerhält den übergeordneten Gültigkeitsbereich Variablenwert, der in der Direktive geändert werden kann.

Wenn Sie mehrere Variablen im übergeordneten Bereich ändern müssen, können Sie eine Funktion im übergeordneten Bereich innerhalb der Direktive ausführen (oder Daten über einen Dienst übergeben).

Asgoth
quelle
1
Ja, diesen Teil bekomme ich, siehe die Geige in der Frage. Aber was ist mit den Teilen, die unklar sind?
iwein
4
Die Sache ist, dass {{}} nicht mit = funktioniert. = wird nicht ausgewertet, aber die Zeichenfolge wird unverändert als Eigenschaftsname verwendet. Danke für die Antwort!
iwein
1
Ich denke nicht, dass = nur für Variablen im übergeordneten Bereich ist. Es funktioniert mit jedem Ausdruck (z. B. 1 + 1).
Jonathan Aquino
1
@ JonathanAquino Sie haben Recht, dass es Ausdrücke auswertet. imho das ist eigentlich komisch und ich würde es nicht so benutzen. Es sind diese cleveren Tricks, die es mir so schwer machen, Richtlinienbereiche überhaupt zu verstehen.
iwein
1
Bin ich der einzige, der diese Antwort für falsch hält! '=' mittlerer Winkel erwartet einen Javascript-Ausdruck und führt eine bidirektionale Zuordnung durch, wenn eine Bereichsvariable übergeben wird. Während @ Mittelwert Winkel einen String erwarten und das alles. In der Tat ist es wahr, dass Sie den Wert der Variablen klonen, wenn Sie @ in Kombination mit {{}} verwenden. Aber es ist nicht die Definition von @!
Luc DUZAN
39

Wenn Sie mehr darüber erfahren möchten, wie dies mit einem Live-Beispiel funktioniert. http://jsfiddle.net/juanmendez/k6chmnch/

var app = angular.module('app', []);
app.controller("myController", function ($scope) {
    $scope.title = "binding";
});
app.directive("jmFind", function () {
    return {
        replace: true,
        restrict: 'C',
        transclude: true,
        scope: {
            title1: "=",
            title2: "@"
        },
        template: "<div><p>{{title1}} {{title2}}</p></div>"
    };
});
Juan Mendez
quelle
2
In der Frage und der Top-Antwort sind mehrere Beispiele verknüpft. Was fügt das hinzu?
iwein
10
@iwein, es fügt Klarheit hinzu. Wenn ich Beispiele mit vollem Funktionsumfang verstehen und verarbeiten könnte, würde ich diese Site nicht benötigen.
Tony Ennis
3
Juan, vielleicht deine Tippfehler korrigieren? 'transclude' ist falsch geschrieben. Besser noch, entfernen Sie es (und alles andere, wie "Ersetzen"), das nicht direkt zum Problem beiträgt, damit Ihre Lösung noch einfacher und klarer wird. +1 für das Beispiel.
Tony Ennis
Vielen Dank an @AnikISlamAbhi für die Bearbeitung. Ich möchte mehr beitragen und bin froh, dass einige meine Beispiele hilfreich finden. Das ist der Hauptzweck.
Juan Mendez
Unvollständiges Beispiel. In Ihrer Demonstration ändern Sie nur den bidirektionalen Wert. Sie versuchen nicht einmal, einen Wert zu ändern, der einen isolierten Bereich hat. Es wird also nicht richtig demonstriert, wie der Geltungsbereich in Richtlinien funktioniert.
Sudarshan_SMD
38

@ als Zeichenfolge erhalten

  • Dadurch entstehen keinerlei Bindungen. Sie erhalten einfach das Wort, das Sie als Zeichenfolge eingegeben haben

= 2-Wege-Bindung

  • Vom Controller vorgenommene Änderungen werden in der Referenz der Richtlinie berücksichtigt und umgekehrt

&Dies verhält sich etwas anders, da der Bereich eine Funktion erhält, die das übergebene Objekt zurückgibt . Ich gehe davon aus, dass dies notwendig war, damit es funktioniert. Die Geige sollte dies klarstellen.

  • Nach dem Aufruf dieser Getter-Funktion verhält sich das resultierende Objekt wie folgt:
    • Wenn eine Funktion übergeben wurde, wird die Funktion beim Aufruf im übergeordneten (Controller-) Abschluss ausgeführt
    • Wenn eine Nichtfunktion übergeben wurde: Holen Sie sich einfach eine lokale Kopie des Objekts ohne Bindungen


Diese Geige sollte zeigen, wie sie funktionieren . Achten Sie besonders auf die Scope-Funktionen get...im Namen, um hoffentlich besser zu verstehen, was ich meine&

geg
quelle
36

Es gibt drei Möglichkeiten, wie der Richtlinie Geltungsbereich hinzugefügt werden kann:

  1. Übergeordneter Bereich : Dies ist die Standardbereichsvererbung.

Die Direktive und ihr übergeordneter Bereich (Controller / Direktive, in dem sie liegt) sind identisch. Alle Änderungen, die an den Bereichsvariablen in der Direktive vorgenommen werden, werden daher auch im übergeordneten Controller wiedergegeben. Sie müssen dies nicht angeben, da dies die Standardeinstellung ist.

  1. Untergeordneter Bereich : Die Direktive erstellt einen untergeordneten Bereich, der vom übergeordneten Bereich erbt, wenn Sie die Bereichsvariable der Direktive als true angeben.

Wenn Sie hier die Bereichsvariablen innerhalb der Direktive ändern, wird dies nicht im übergeordneten Bereich angezeigt. Wenn Sie jedoch die Eigenschaft einer Bereichsvariablen ändern, die sich im übergeordneten Bereich widerspiegelt, haben Sie die Bereichsvariable des übergeordneten Bereichs tatsächlich geändert .

Beispiel,

app.directive("myDirective", function(){

    return {
        restrict: "EA",
        scope: true,
        link: function(element, scope, attrs){
            scope.somvar = "new value"; //doesnot reflect in the parent scope
            scope.someObj.someProp = "new value"; //reflects as someObj is of parent, we modified that but did not override.
        }
    };
});
  1. Isolierter Bereich : Dies wird verwendet, wenn Sie den Bereich erstellen möchten, der nicht vom Controller-Bereich erbt.

Dies geschieht, wenn Sie Plugins erstellen, da dies die Direktive generisch macht, da sie in jedem HTML-Code platziert werden kann und nicht vom übergeordneten Bereich beeinflusst wird.

Wenn Sie keine Interaktion mit dem übergeordneten Bereich wünschen, können Sie den Bereich einfach als leeres Objekt angeben. mögen,

scope: {} //this does not interact with the parent scope in any way

Meistens ist dies nicht der Fall, da wir eine Interaktion mit dem übergeordneten Bereich benötigen. Daher möchten wir, dass einige der Werte / Änderungen durchlaufen werden. Aus diesem Grund verwenden wir:

1. "@"   (  Text binding / one-way binding )
2. "="   ( Direct model binding / two-way binding )
3. "&"   ( Behaviour binding / Method binding  )

@ bedeutet, dass die Änderungen aus dem Controller-Bereich im Direktivenbereich übernommen werden. Wenn Sie jedoch den Wert im Direktivenbereich ändern, wird die Controller-Bereichsvariable nicht beeinflusst.

@ erwartet immer, dass das zugeordnete Attribut ein Ausdruck ist. Dies ist sehr wichtig; Da das Präfix "@" funktioniert, müssen wir den Attributwert in {{}} einschließen.

= ist bidirektional. Wenn Sie also die Variable im Direktivenbereich ändern, wird auch die Variable des Controller-Bereichs beeinflusst

& wird verwendet, um die Controller-Scope-Methode zu binden, damit wir sie bei Bedarf aus der Direktive aufrufen können

Der Vorteil hierbei ist, dass der Name der Variablen im Bereich des Controllers und der Direktive nicht identisch sein muss.

Beispiel: Der Direktivenbereich hat eine Variable "dirVar", die mit der Variablen "contVar" des Controller-Bereichs synchronisiert wird. Dies verleiht der Direktive viel Leistung und Verallgemeinerung, da ein Controller mit der Variablen v1 synchronisieren kann, während ein anderer Controller, der dieselbe Direktive verwendet, dirVar auffordern kann, mit der Variablen v2 zu synchronisieren.

Unten ist das Anwendungsbeispiel:

Die Richtlinie und der Controller sind:

 var app = angular.module("app", []);
 app.controller("MainCtrl", function( $scope ){
    $scope.name = "Harry";
    $scope.color = "#333333";
    $scope.reverseName = function(){
     $scope.name = $scope.name.split("").reverse().join("");
    };
    $scope.randomColor = function(){
        $scope.color = '#'+Math.floor(Math.random()*16777215).toString(16);
    };
});
app.directive("myDirective", function(){
    return {
        restrict: "EA",
        scope: {
            name: "@",
            color: "=",
            reverse: "&"
        },
        link: function(element, scope, attrs){
           //do something like
           $scope.reverse(); 
          //calling the controllers function
        }
    };
});

Und das HTML (beachten Sie den Unterschied für @ und =):

<div my-directive
  class="directive"
  name="{{name}}"
  reverse="reverseName()"
  color="color" >
</div>

Hier ist ein Link zum Blog, der es schön beschreibt.

Kop4lyf
quelle
& ist weder "Verhaltensbindung" noch "Methodenbindung", es ist Angular Expression Binding.
Dmitri Zaitsev
20

Einfach können wir verwenden: -

  1. @ : - für Zeichenfolgenwerte für eine Einwegdatenbindung. Auf eine Weise können Sie die Datenbindung nur an die Direktive übergeben

  2. = : - für Objektwert für bidirektionale Datenbindung. Auf zwei Arten können Sie den Gültigkeitsbereich sowohl in der Direktive als auch in HTML ändern.

  3. & : - für Methoden und Funktionen.

BEARBEITEN

In unserer Komponentendefinition für Angular Version 1.5 und höher
gibt es vier verschiedene Arten von Bindungen:

  1. = Zweiwege-Datenbindung : - Wenn wir den Wert ändern, wird er automatisch aktualisiert
  2. < Einwegbindung : - Wenn wir nur einen Parameter aus einem übergeordneten Bereich lesen und nicht aktualisieren möchten.

  3. @Dies gilt für Zeichenfolgenparameter

  4. &Dies gilt für Rückrufe, falls Ihre Komponente etwas in ihrem übergeordneten Bereich ausgeben muss

ojus kulkarni
quelle
13

Ich habe eine kleine HTML-Datei erstellt, die Angular-Code enthält, der die Unterschiede zwischen ihnen demonstriert:

<!DOCTYPE html>
<html>
  <head>
    <title>Angular</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="myCtrl as VM">
      <a my-dir
        attr1="VM.sayHi('Juan')" <!-- scope: "=" -->
        attr2="VM.sayHi('Juan')" <!-- scope: "@" -->
        attr3="VM.sayHi('Juan')" <!-- scope: "&" -->
      ></a>
    </div>
    <script>
    angular.module("myApp", [])
    .controller("myCtrl", [function(){
      var vm = this;
      vm.sayHi = function(name){
        return ("Hey there, " + name);
      }
    }])
    .directive("myDir", [function(){
      return {
        scope: {
          attr1: "=",
          attr2: "@",
          attr3: "&"
        },
        link: function(scope){
          console.log(scope.attr1);   // =, logs "Hey there, Juan"
          console.log(scope.attr2);   // @, logs "VM.sayHi('Juan')"
          console.log(scope.attr3);   // &, logs "function (a){return h(c,a)}"
          console.log(scope.attr3()); // &, logs "Hey there, Juan"
        }
      }
    }]);
    </script>
  </body>
</html>
RobertAKARobin
quelle
6

Der = Weg ist eine 2-Wege-Bindung , mit der Sie Live- Änderungen in Ihrer Direktive vornehmen können. Wenn jemand diese Variable aus der Direktive heraus ändert, haben Sie diese geänderten Daten in Ihrer Direktive, aber @ way ist keine bidirektionale Bindung . Es funktioniert wie Text . Sie binden einmal und Sie haben nur seinen Wert.

Um es klarer zu machen, können Sie diesen großartigen Artikel verwenden:

Geltungsbereich der AngularJS-Richtlinie '@' und '='

Hazarapet Tunanyan
quelle
6

Diese Frage wurde bereits zu Tode geprügelt, aber ich werde sie trotzdem teilen, falls jemand anderes da draußen mit dem schrecklichen Durcheinander von AngularJS zu kämpfen hat. Dies wird Abdeckung =, <, @, &und ::. Die vollständige Beschreibung finden Sie hier .


=stellt eine wechselseitige Bindung her. Das Ändern der Eigenschaft im übergeordneten Element führt zu einer Änderung des untergeordneten Elements und umgekehrt.


<stellt eine Einwegbindung zwischen Eltern und Kind her. Das Ändern der Eigenschaft im übergeordneten Element führt zu einer Änderung des untergeordneten Elements, das Ändern der untergeordneten Eigenschaft wirkt sich jedoch nicht auf die übergeordnete Eigenschaft aus.


@weist der untergeordneten Eigenschaft den Zeichenfolgenwert des Tag-Attributs zu. Wenn das Attribut einen Ausdruck enthält , wird die untergeordnete Eigenschaft immer dann aktualisiert, wenn der Ausdruck eine andere Zeichenfolge ergibt. Zum Beispiel:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

Hier ist die descriptionEigenschaft im untergeordneten Bereich der aktuelle Wert des Ausdrucks "The movie title is {{$ctrl.movie.title}}", wobei moviees sich um ein Objekt im übergeordneten Bereich handelt.


&ist ein bisschen knifflig, und tatsächlich scheint es keinen zwingenden Grund zu geben, es jemals zu benutzen. Sie können einen Ausdruck im übergeordneten Bereich auswerten und Parameter durch Variablen aus dem untergeordneten Bereich ersetzen. Ein Beispiel ( plunk ):

<child-component 
  foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
  template: "<div>{{  $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'})  }}</div>",
  bindings: {
    parentFoo: '&foo'
  }
});

Gegeben parentVar=10, der Ausdruck parentFoo({myVar:5, myOtherVar:'xyz'})wird ausgewertet 5 + 10 + 'xyz'und die Komponente wird wie folgt gerendert:

<div>15xyz</div>

Wann würden Sie jemals diese verschlungene Funktionalität nutzen wollen? &wird häufig von Personen verwendet, um eine Rückruffunktion im übergeordneten Bereich an den untergeordneten Bereich zu übergeben. In der Realität kann der gleiche Effekt jedoch erzielt werden, indem '<' zum Übergeben der Funktion verwendet wird. Dies ist einfacher und vermeidet die umständliche Syntax geschweifter Klammern zum Übergeben von Parametern ( {myVar:5, myOtherVar:'xyz'}). Erwägen:

Rückruf mit &:

<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
  bindings: {
    parentFoo: '&'
  }
});

Rückruf mit <:

<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
  template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
  bindings: {
    parentFoo: '<'
  }
});

Beachten Sie, dass Objekte (und Arrays) unter Bezugnahme auf den untergeordneten Bereich übergeben und nicht kopiert werden. Dies bedeutet, dass Sie, selbst wenn es sich um eine Einwegbindung handelt, sowohl im übergeordneten als auch im untergeordneten Bereich mit demselben Objekt arbeiten.


Öffnen Sie diesen Plunk , um die verschiedenen Präfixe in Aktion zu sehen .

Einmalige Bindung (Initialisierung) mit ::

[Offizielle Dokumente] In
späteren Versionen von AngularJS wird die Option einer einmaligen Bindung eingeführt, bei der die Eigenschaft des untergeordneten Bereichs nur einmal aktualisiert wird. Dies verbessert die Leistung, da die übergeordnete Eigenschaft nicht mehr überwacht werden muss. Die Syntax unterscheidet sich von oben; Um eine einmalige Bindung zu deklarieren, fügen Sie ::vor dem Ausdruck im Komponenten-Tag Folgendes hinzu :

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

Dadurch wird der Wert von taglinean den untergeordneten Bereich weitergegeben, ohne dass eine Einweg- oder Zweiwegbindung hergestellt wird. Hinweis : Wenn sich taglineAngular ursprünglich undefinedim übergeordneten Bereich befindet, wird es von Angular überwacht, bis es sich ändert, und anschließend wird die entsprechende Eigenschaft im untergeordneten Bereich einmalig aktualisiert.

Zusammenfassung

Die folgende Tabelle zeigt, wie die Präfixe funktionieren, je nachdem, ob es sich bei der Eigenschaft um ein Objekt, ein Array, eine Zeichenfolge usw. handelt.

Funktionsweise der verschiedenen Isolationsbereichsbindungen

Mihail Kostira
quelle
4

Die Eigenschaft @ local scope wird verwendet, um auf Zeichenfolgenwerte zuzugreifen, die außerhalb der Direktive definiert sind.

= In Fällen, in denen Sie eine bidirektionale Bindung zwischen dem äußeren Bereich und dem isolierten Bereich der Direktive erstellen müssen, können Sie das Zeichen = verwenden.

Mit der Eigenschaft & local scope kann der Verbraucher einer Direktive eine Funktion übergeben, die die Direktive aufrufen kann.

Bitte überprüfen Sie den folgenden Link, der Ihnen ein klares Verständnis mit Beispielen gibt. Ich fand es wirklich sehr nützlich, also dachte ich daran, es zu teilen.

http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-2-isolate-scope

Raphael
quelle
3

Auch wenn der Bereich lokal ist, wie in Ihrem Beispiel, können Sie über die Eigenschaft auf den übergeordneten Bereich zugreifen $parent. Nehmen Sie im folgenden Code titlean, der im übergeordneten Bereich definiert ist. Sie können dann auf den Titel zugreifen als $parent.title:

link : function(scope) { console.log(scope.$parent.title) },
template : "the parent has the title {{$parent.title}}"

In den meisten Fällen wird der gleiche Effekt jedoch besser mit Attributen erzielt.

Ein Beispiel dafür, wo ich die Notation "&" gefunden habe, die verwendet wird, um "Daten aus dem isolierten Bereich über einen Ausdruck an den übergeordneten Bereich zu übergeben", war nützlich (und eine bidirektionale Datenbindung konnte nicht verwendet werden), war in einer Direktive zum Rendern einer speziellen Datenstruktur innerhalb einer ng-Wiederholung.

<render data = "record" deleteFunction = "dataList.splice($index,1)" ng-repeat = "record in dataList" > </render>

Ein Teil des Renderings war eine Schaltfläche zum Löschen. Hier war es nützlich, eine Löschfunktion aus dem externen Bereich über & anzuhängen. Innerhalb der Render-Direktive sieht es so aus

scope : { data = "=", deleteFunction = "&"},
template : "... <button ng-click = "deleteFunction()"></button>"

Die bidirektionale Datenbindung data = "="kann nicht verwendet werden, da die Löschfunktion in jedem $digestZyklus ausgeführt wird, was nicht gut ist, da der Datensatz dann sofort gelöscht und nie gerendert wird.

user3750988
quelle
3

Ich habe alle möglichen Optionen in einer Geige implementiert.

Es behandelt alle Optionen:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm

Rishul Matta
quelle
3

Der Hauptunterschied zwischen ihnen ist gerecht

@ Attribute string binding
= Two-way model binding
& Callback method binding
Ashish Kamble
quelle
1

@und =andere Antworten sehen.

Ein Gotcha über TL; DR; Ruft einen Ausdruck (nicht nur wie in Beispielen in anderen Antworten) von einem übergeordneten Element ab und legt ihn als Funktion in der Direktive fest, die den Ausdruck aufruft. Diese Funktion kann jede Variable (sogar den Funktionsnamen) des Ausdrucks ersetzen , indem ein Objekt mit den Variablen übergeben wird. &

&

erklärt
& ist eine Ausdrucksreferenz, das heißt, wenn Sie etwas wie <myDirective expr="x==y"></myDirective>
in der Direktive übergeben, ist dies expreine Funktion, die den Ausdruck aufruft, wie :
function expr(){return x == y}.
In der Direktive <button ng-click="expr()"></button>ruft HTML den Ausdruck auf. In js der Direktive wird nur $scope.expr()auch der Ausdruck aufgerufen.
Der Ausdruck wird mit $ scope.x und $ scope.y des übergeordneten Elements aufgerufen.
Sie haben die Möglichkeit, die Parameter zu überschreiben!
Wenn Sie sie per Aufruf festlegen, z. B., <button ng-click="expr({x:5})"></button>
wird der Ausdruck mit Ihrem Parameter xund dem Parameter der Eltern aufgerufen y.
Sie können beide überschreiben.
Jetzt wissen Sie, warum ) und ersetzen in diesem Fall mögliche Werte durch Ihre angegebenen Parameter .<button ng-click="functionFromParent({x:5})"></button> funktioniert.
Weil es nur den Ausdruck des Elternteils nennt (z<myDirective functionFromParent="function1(x)"></myDirective>x
es könnte sein:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
oder
<myDirective functionFromParent="function1(x) + z"></myDirective>
mit Kinderanruf :
<button ng-click="functionFromParent({x:5, z: 4})"></button>.
oder sogar mit Funktionsaustausch:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button> .

Es ist nur ein Ausdruck, egal ob es sich um eine Funktion oder viele Funktionen oder nur um einen Vergleich handelt. Und Sie können jeden ersetzen Variable dieses Ausdrucks .

Beispiele:
Richtlinie Vorlage vs genannt Code:
Eltern $ scope.x definiert hat, $ scope.y:
Eltern Vorlage: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>Anrufe $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>Anrufe 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>Anrufe5 == 6

Eltern hat $ scope.function1, $ scope.x, $ scope.y definiert:
Elternvorlage:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>Anrufe $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>Anrufe $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>Anrufe $scope.function1(5) + 6
Richtlinie hat $ scope.myFn als Funktion:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> Anrufe$scope.myFn(5) + 6

ya_dimon
quelle
0

Warum muss ich "{{title}}" mit '@' und "title" mit '=' verwenden?

Wenn Sie {{title}} verwenden, wird nur der übergeordnete Bereichswert an die Direktivenansicht übergeben und ausgewertet. Dies ist auf eine Möglichkeit beschränkt, was bedeutet, dass Änderungen nicht im übergeordneten Bereich berücksichtigt werden. Sie können '=' verwenden, wenn Sie die Änderungen in der untergeordneten Direktive auch im übergeordneten Bereich widerspiegeln möchten. Dies ist in beide Richtungen.

Kann ich auch direkt auf den übergeordneten Bereich zugreifen, ohne mein Element mit einem Attribut zu dekorieren?

Wenn die Direktive das Attribut scope enthält (scope: {}), können Sie nicht mehr direkt auf den übergeordneten Bereich zugreifen. Es ist jedoch weiterhin möglich, über scope. $ Parent usw. darauf zuzugreifen. Wenn Sie scope aus der Direktive entfernen, kann direkt darauf zugegriffen werden.

In der Dokumentation heißt es: "Oft ist es wünschenswert, Daten aus dem isolierten Bereich über einen Ausdruck an den übergeordneten Bereich zu übergeben." Dies scheint jedoch auch bei bidirektionaler Bindung gut zu funktionieren. Warum sollte die Ausdrucksroute besser sein?

Es hängt vom Kontext ab. Wenn Sie einen Ausdruck oder eine Funktion mit Daten aufrufen möchten, verwenden Sie &, und wenn Sie Daten freigeben möchten, können Sie die bidirektionale Methode mit '=' verwenden.

Die Unterschiede zwischen mehreren Arten der Datenübergabe an die Direktive finden Sie unter folgendem Link:

AngularJS - Isolierte Bereiche - @ vs = vs &

http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs

Prashanth
quelle
0

@ Attributzeichenfolgenbindung (Einweg) = Zweiwegmodellbindung und Rückrufmethodenbindung

Jatin Patel
quelle
0

@ bindet eine Eigenschaft local / directive scope an den ausgewerteten Wert des DOM-Attributs. = bindet eine lokale / direktive Bereichseigenschaft an eine übergeordnete Bereichseigenschaft. & Binding dient zum Übergeben einer Methode in den Geltungsbereich Ihrer Direktive, damit sie innerhalb Ihrer Direktive aufgerufen werden kann.

@ Attribute string binding = Zweiwege-Modellbindung und Callback-Methodenbindung

Ashish Kamble
quelle