Qual è la differenza tra '@' e '=' nell'ambito della direttiva in AngularJS?


1067

Ho letto attentamente la documentazione di AngularJS sull'argomento, e poi ho armeggiato con una direttiva. Ecco il violino .

E qui ci sono alcuni frammenti rilevanti:

  • Dal HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • Dalla direttiva riquadro:

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

Ci sono diverse cose che non capisco:

  • Perché devo usare "{{title}}"con '@'e "title"con '='?
  • Posso anche accedere direttamente all'ambito padre, senza decorare il mio elemento con un attributo?
  • La documentazione dice "Spesso è desiderabile passare i dati dall'ambito isolato tramite espressione e all'ambito padre" , ma sembra funzionare bene anche con l'associazione bidirezionale. Perché l'espressione route sarebbe migliore?

Ho trovato un altro violino che mostra anche la soluzione di espressione: http://jsfiddle.net/maxisam/QrCXh/


18
Punto valido. La capacità di ricercare e trovare risposte è importante.
Jonathan,


1
In parole semplici, =viene utilizzato nel campo di applicazione dell'isolato della direttiva per consentire l'associazione bidirezionale e @non aggiorna il modello, ma aggiorna solo i valori dell'ambito della direttiva.
ACCIAIO,

@iwein perché il tuo codice di violino su jsfiddle.net/maxisam/QrCXh non funziona con googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Il tuo codice funziona solo se uso il tuo cdn - code.angularjs.org/1.0.1/angular-1.0.1.js
MukulSharma

Vedo molte buone risposte di seguito, ma qualcuno può dare un puntatore alla documentazione angolare ufficiale che risponde a questa domanda?
John Henckel,

Risposte:


1151

Perché devo usare "{{title}}" con ' @ ' e "title" con ' = '?

@ associa una proprietà scope locale / direttiva al valore valutato dell'attributo DOM . Se si utilizza title=title1o title="title1", il valore dell'attributo DOM "title" è semplicemente la stringa title1. Se si utilizza title="{{title}}", il valore dell'attributo DOM "title" è il valore interpolato di {{title}}, quindi la stringa sarà la proprietà dell'ambito padre "title" attualmente impostata. Poiché i valori degli attributi sono sempre stringhe, quando si utilizza @ si finirà sempre con un valore di stringa per questa proprietà nell'ambito della direttiva .

= associa una proprietà scope locale / direttiva a una proprietà scope padre . Pertanto, con = , si utilizza il nome della proprietà modello / ambito padre come valore dell'attributo DOM. Non puoi usare {{}}s con = .

Con @, puoi fare cose come title="{{title}} and then some"- {{title}} viene interpolato, quindi la stringa "e loro un po '" viene concatenata con essa. La stringa concatenata finale è quella che ottiene la proprietà scope locale / direttiva. (Non puoi farlo con = , solo @ .)

Con @ , dovrai usare attr.$observe('title', function(value) { ... })se devi usare il valore nella tua funzione link (ing). Ad esempio, if(scope.title == "...")non funzionerà come previsto. Si noti che ciò significa che è possibile accedere a questo attributo solo in modo asincrono . Non è necessario utilizzare $ observ () se si utilizza solo il valore in un modello. Ad es template: '<div>{{title}}</div>'.

Con = , non è necessario utilizzare $ observ.

Posso anche accedere direttamente all'ambito padre, senza decorare il mio elemento con un attributo?

Sì, ma solo se non si utilizza un ambito isolato. Rimuovi questa linea dalla tua direttiva

scope: { ... }

e quindi la tua direttiva non creerà un nuovo ambito. Utilizzerà l'ambito padre. È quindi possibile accedere direttamente a tutte le proprietà dell'ambito padre.

La documentazione dice "Spesso è desiderabile passare i dati dall'ambito isolato tramite un'espressione e all'ambito padre", ma questo sembra funzionare bene anche con l'associazione bidirezionale. Perché l'espressione route sarebbe migliore?

Sì, l'associazione bidirezionale consente all'ambito locale / direttiva e all'ambito padre di condividere i dati. "Associazione di espressioni" consente alla direttiva di chiamare un'espressione (o una funzione) definita da un attributo DOM - e puoi anche passare i dati come argomenti all'espressione o alla funzione. Quindi, se non hai bisogno di condividere dati con il genitore - vuoi solo chiamare una funzione definita nell'ambito genitore - puoi usare la sintassi & .

Guarda anche


1
Eh, questo è un comportamento davvero strano, specialmente quando non si usa l'interpolazione e si cerca di passare una stringa. Apparentemente la richiesta pull è stata effettivamente unita alle build di sviluppo ed è nelle build RC 1.1.5 e 1.2.0. Buono per loro per aver risolto questo comportamento molto poco intuitivo!
Ibrahim,

50
Scrivere '@' o '=' è molto più chiaro che scrivere "eval-dom" o "parent-scope" o qualsiasi altro testo leggibile dall'uomo. Buona decisione progettuale.
Den

13
@('at') copia il valore di 'ATtribute'. =('uguale a') equivale a dire che la chiave è uguale alla tua espressione. Questo, almeno, è come li tengo stretti.
Matt DeKrey,

1
Sei sicuro che = sia solo per le proprietà dell'ambito genitore? Qualsiasi espressione sembra funzionare, non solo le proprietà dell'ambito genitore.
Jonathan Aquino,

4
@JonathanAquino, sì, funziona, ma @ sarebbe più appropriato - con foo="{{1+1}}"- perché non abbiamo bisogno di un'associazione dati bidirezionale qui. Il punto che ho cercato di fare nel commento sopra è che dovremmo usare = solo quando la direttiva ha bisogno di un'associazione di dati bidirezionale. Usa @ o & altrimenti.
Mark Rajcok,

542

Ci sono un sacco di grandi risposte qui, ma vorrei offrire il mio punto di vista sulle differenze tra @, =e &di legame che si è rivelato utile per me.

Tutti e tre i binding sono modi per trasferire i dati dall'ambito padre all'ambito isolato della direttiva attraverso gli attributi dell'elemento:

  1. Il bind @ serve per passare le stringhe. Queste stringhe supportano {{}}espressioni per valori interpolati. Per esempio: . L'espressione interpolata viene valutata in base all'ambito padre della direttiva.

  2. = l' associazione è per l'associazione modello bidirezionale. Il modello in ambito padre è collegato al modello in ambito isolato della direttiva. Le modifiche a un modello influiscono sull'altro e viceversa.

  3. & associazione è per passare un metodo nell'ambito della direttiva in modo che possa essere chiamato all'interno della direttiva. Il metodo è pre-associato all'ambito padre della direttiva e supporta argomenti. Ad esempio se il metodo è ciao (nome) nell'ambito genitore, quindi per eseguire il metodo dall'interno della direttiva, è necessario chiamare $ scope.hello ({nome: 'mondo'})

Trovo che sia più facile ricordare queste differenze facendo riferimento ai vincoli dell'ambito con una descrizione più breve:

  • @ Associazione di stringhe di attributi
  • = Rilegatura modello a due vie
  • & Associazione del metodo di callback

I simboli chiariscono anche cosa rappresenta la variabile scope nell'ambito dell'implementazione della direttiva:

  • @ corda
  • = modello
  • & metodo

In ordine di utilità (per me comunque):

  1. =
  2. @
  3. &

13
In realtà, "&"supporta gli argomenti (o, piuttosto, i locali) del modulo:, callback({foo: "some value"})che potrebbe quindi essere utilizzato <my-dir callback="doSomething(foo)">. Altrimenti, buona risposta
Nuovo Dev

11
Dovrebbe essere accettata la risposta. Ecco un articolo conciso con le stesse informazioni, ma con esempi di codice aggiunti: umur.io/…
Kevin,

4
e NON è "Associazione metodo di callback", è associazione di espressione angolare. Un esempio speciale ma non l'unico è l'espressione callback(argument). Che non è ancora lo stesso di se callbackstesso.
Dmitri Zaitsev,

14
Mentre mi è piaciuto quanto fosse definitiva la risposta di livello superiore, ho scoperto che questa ha avuto un impatto più utile e dopo aver letto questa ho capito molto di più la risposta precedente.
rbnzdave,

1
Concordo con il commento precedente, questa risposta è più chiara, definitiva e utile alla domanda. Spiega con sufficiente dettaglio che puoi andare e utilizzare le informazioni.
user3125823

64

Il =mezzo indica un legame bidirezionale, quindi un riferimento a una variabile rispetto all'ambito padre. Ciò significa che, quando si modifica la variabile nella direttiva, anche questa verrà modificata nell'ambito genitore.

@ significa che la variabile verrà copiata (clonata) nella direttiva.

Per quanto ne so, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>dovrebbe funzionare anche. bi-titlericeverà il valore della variabile dell'ambito padre, che può essere modificato nella direttiva.

Se è necessario modificare diverse variabili nell'ambito genitore, è possibile eseguire una funzione nell'ambito genitore dalla direttiva (o passare i dati tramite un servizio).


1
Sì, quella parte che ottengo, vedi il violino nella domanda. Ma per quanto riguarda le parti che non sono chiare?
Iwein

4
il fatto è che {{}} non funziona con =. = non viene valutato, ma la stringa viene considerata come il nome della proprietà così com'è. Grazie per la risposta!
iwein,

1
Non penso che = sia solo per variabili nell'ambito genitore. Funziona con qualsiasi espressione (ad es. 1 + 1).
Jonathan Aquino,

1
@JonathanAquino hai ragione nel valutare le espressioni. imho questo è in realtà strano e non lo userei in questo modo. È questo tipo di trucchi intelligenti che rendono gli scopi della direttiva così difficili da capire per me in primo luogo.
iwein,

1
Sono l'unico a pensare che questa risposta sia sbagliata! '=' significa che angolare si aspetta un'espressione javascript e eseguirà una mappatura bidirezionale se viene passata una variabile ambito. Mentre @ mean angular si aspetta una stringa e tutto il resto. In effetti, è vero che se usi @ in combinazione con {{}} clonerai il valore della variabile. Ma non è la definizione di @!
Luc DUZAN,

39

Se vuoi vedere di più come funziona con un esempio dal vivo. 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>"
    };
});

2
Ci sono molti esempi collegati nella domanda e nella risposta migliore. Cosa aggiunge questo?
iwein

10
@wewein, aggiunge chiarezza. Se potessi comprendere e assimilare esempi completi, non avrei bisogno di questo sito.
Tony Ennis,

3
juan, forse correggi i tuoi errori di battitura? 'transclude' è scritto male. meglio ancora, rimuoverlo (e tutto il resto, come 'sostituisci') che non contribuisce direttamente al problema, quindi la tua soluzione è ancora più semplice e chiara. +1 per l'esempio.
Tony Ennis,

grazie @AnikISlamAbhi per l'editing. Vorrei contribuire di più e sono contento che alcuni trovino utili i miei campioni. Questo è lo scopo principale.
Juan Mendez,

Esempio incompleto. Nella tua dimostrazione, stai cambiando solo il valore bidirezionale. Non stai nemmeno cercando di cambiare valore che ha un ambito isolato. Pertanto, non ha dimostrato correttamente come funziona l'ambito di applicazione nelle direttive.
Sudarshan_SMD

38

@ prendi come stringa

  • Questo non crea alcun vincolo di sorta. Stai semplicemente ottenendo la parola che hai passato come una stringa

= Rilegatura a 2 vie

  • le modifiche apportate dal responsabile del trattamento si rifletteranno nel riferimento contenuto nella direttiva e viceversa

&Ciò si comporta in modo leggermente diverso, poiché l'ambito ottiene una funzione che restituisce l'oggetto che è stato passato . Suppongo che questo fosse necessario per farlo funzionare. Il violino dovrebbe chiarirlo.

  • Dopo aver chiamato questa funzione getter, l'oggetto risultante si comporta come segue:
    • se è stata passata una funzione : la funzione viene eseguita nella chiusura principale (controller) quando viene chiamata
    • se è stata passata una non funzione : è sufficiente ottenere una copia locale dell'oggetto che non ha legami


Questo violino dovrebbe dimostrare come funzionano . Presta particolare attenzione alle funzioni dell'ambito con get...nel nome, speriamo di capire meglio cosa intendo&


36

Esistono tre modi in cui è possibile aggiungere l'ambito di applicazione nella direttiva:

  1. Ambito principale : questa è l'ereditarietà predefinita dell'ambito.

La direttiva e il relativo ambito (controllore / direttiva all'interno del quale si trova) è lo stesso. Pertanto, qualsiasi modifica apportata alle variabili dell'ambito all'interno della direttiva si riflette anche nel controller principale. Non è necessario specificarlo poiché è il valore predefinito.

  1. Ambito figlio : direttiva crea un ambito figlio che eredita dall'ambito padre se si specifica la variabile ambito della direttiva come vera.

In questo caso, se si modificano le variabili dell'ambito all'interno della direttiva, non si rifletterà nell'ambito padre, ma se si modifica la proprietà di una variabile dell'ambito, che si riflette nell'ambito padre, poiché in realtà è stata modificata la variabile ambito del padre .

Esempio,

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. Portata isolata : viene utilizzato quando si desidera creare l'ambito che non eredita dall'ambito del controller.

Questo succede quando si creano plugin in quanto ciò rende la direttiva generica poiché può essere inserita in qualsiasi HTML e non viene influenzata dal suo ambito padre.

Ora, se non desideri alcuna interazione con l'ambito padre, puoi semplicemente specificare l'ambito come oggetto vuoto. piace,

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

Principalmente questo non è il caso in cui abbiamo bisogno di una certa interazione con l'ambito padre, quindi vogliamo che alcuni dei valori / cambiamenti passino. Per questo motivo, utilizziamo:

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

@ indica che le modifiche dall'ambito del controller si rifletteranno nell'ambito della direttiva ma se si modifica il valore nell'ambito della direttiva, la variabile dell'ambito del controller non verrà influenzata.

@ si aspetta sempre che l'attributo mappato sia un'espressione. Questo è molto importante; perché per far funzionare il prefisso "@", dobbiamo racchiudere il valore dell'attributo in {{}}.

= è bidirezionale, quindi se si modifica la variabile nell'ambito della direttiva, anche la variabile dell'ambito del controller viene interessata

e viene utilizzato per associare il metodo dell'ambito del controller in modo che, se necessario, possiamo chiamarlo dalla direttiva

Il vantaggio qui è che il nome della variabile non deve necessariamente essere lo stesso nell'ambito del controller e nell'ambito della direttiva.

Ad esempio, l'ambito della direttiva ha una variabile "dirVar" che si sincronizza con la variabile "contVar" dell'ambito del controller. Ciò fornisce molta potenza e generalizzazione alla direttiva poiché un controller può sincronizzarsi con la variabile v1 mentre un altro controller che utilizza la stessa direttiva può chiedere a dirVar di sincronizzarsi con la variabile v2.

Di seguito è riportato l'esempio di utilizzo:

La direttiva e il controller sono:

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

E l'html (nota la differenza per @ e =):

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

Ecco un link al blog che lo descrive bene.


& non è né "associazione di comportamento" né "associazione di metodo", è associazione di espressione angolare.
Dmitri Zaitsev,

20

Semplicemente possiamo usare: -

  1. @ : - per i valori di stringa per l'associazione dati a senso unico. in un modo l'associazione dei dati è possibile solo passare il valore dell'ambito alla direttiva

  2. = : - per valore oggetto per associazione dati bidirezionale. in associazione di dati bidirezionale è possibile modificare il valore di ambito sia in direttiva che in html.

  3. & : - per metodi e funzioni.

MODIFICARE

Nella nostra definizione dei componenti per la versione angolare 1.5 e successive
ci sono quattro diversi tipi di attacchi:

  1. = Associazione dati bidirezionale : - se cambiamo il valore, si aggiorna automaticamente
  2. < associazione unidirezionale : - quando vogliamo solo leggere un parametro da un ambito genitore e non aggiornarlo.

  3. @questo è per Parametri stringa

  4. &questo è per i callback nel caso in cui il componente debba produrre qualcosa nel suo ambito genitore


13

Ho creato un piccolo file HTML che contiene il codice angolare che dimostra le differenze tra loro:

<!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>

6

The = way è un'associazione a 2 vie , che ti consente di avere modifiche in tempo reale all'interno della tua direttiva. Quando qualcuno cambia quella variabile fuori dalla direttiva, avrai quei dati modificati all'interno della tua direttiva, ma @ way non è vincolante in due modi . Funziona come il testo . Ti leghi una volta e avrai solo il suo valore.

Per ottenerlo più chiaramente, puoi usare questo fantastico articolo:

Ambito di applicazione della direttiva AngularJS '@' e '='


6

Questa domanda è già stata picchiata a morte, ma la condividerò comunque nel caso in cui qualcun altro stia lottando con il disastro orribile che è gli scopi di AngularJS. Questa copertura volontà =, <, @, &e ::. La scrittura completa può essere trovata qui .


=stabilisce un'associazione a due vie. La modifica della proprietà nel genitore comporterà la modifica nel figlio e viceversa.


<stabilisce un legame unidirezionale, da genitore a figlio. La modifica della proprietà nel genitore comporterà una modifica nel figlio, ma la modifica della proprietà del figlio non influirà sulla proprietà del genitore.


@assegnerà alla proprietà figlio il valore stringa dell'attributo tag. Se l'attributo contiene un'espressione , la proprietà figlio si aggiorna ogni volta che l'espressione restituisce una stringa diversa. Per esempio:

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

Qui, la descriptionproprietà nell'ambito secondario sarà il valore corrente dell'espressione "The movie title is {{$ctrl.movie.title}}", dove si movietrova un oggetto nell'ambito secondario.


&è un po 'complicato, e in effetti non sembra esserci alcun motivo convincente per usarlo mai. Consente di valutare un'espressione nell'ambito genitore, sostituendo i parametri con variabili dall'ambito figlio. Un esempio ( 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'
  }
});

Dato parentVar=10, l'espressione parentFoo({myVar:5, myOtherVar:'xyz'})verrà valutata 5 + 10 + 'xyz'e il componente verrà visualizzato come:

<div>15xyz</div>

Quando vorresti mai usare questa funzionalità contorta? &viene spesso utilizzato dalle persone per passare all'ambito figlio una funzione di richiamata nell'ambito padre. In realtà, tuttavia, lo stesso effetto può essere ottenuto usando '<' per passare la funzione, che è più semplice ed evita la sintassi di parentesi graffe goffe per passare parametri ( {myVar:5, myOtherVar:'xyz'}). Prendere in considerazione:

Richiamata utilizzando &:

<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: '&'
  }
});

Richiamata utilizzando <:

<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: '<'
  }
});

Si noti che gli oggetti (e le matrici) vengono passati in riferimento all'ambito figlio, non copiati. Ciò significa che anche se si tratta di un'associazione unidirezionale, si sta lavorando con lo stesso oggetto sia nell'ambito padre che figlio.


Per vedere i diversi prefissi in azione, apri questo plunk .

Rilegatura singola (inizializzazione) utilizzando ::

[Documenti ufficiali]
Le versioni successive di AngularJS introducono l'opzione per avere un'associazione unica, in cui la proprietà dell'ambito figlio viene aggiornata una sola volta. Ciò migliora le prestazioni eliminando la necessità di controllare la proprietà padre. La sintassi è diversa da quella sopra; per dichiarare un'associazione una tantum, aggiungi ::davanti all'espressione nel tag del componente :

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

Questo propagherà il valore taglinedell'ambito figlio senza stabilire un'associazione unidirezionale o bidirezionale. Nota : se taglineè inizialmente undefinednell'ambito genitore, angolare lo controllerà fino a quando non cambia e quindi effettua un aggiornamento una tantum della proprietà corrispondente nell'ambito secondario.

Sommario

La tabella seguente mostra come funzionano i prefissi a seconda che la proprietà sia un oggetto, un array, una stringa, ecc.

Come funzionano i vari binding dell'oscilloscopio


4

La proprietà @ ambito locale viene utilizzata per accedere ai valori di stringa definiti al di fuori della direttiva.

= Nei casi in cui è necessario creare un'associazione bidirezionale tra l'ambito esterno e l'ambito di isolamento della direttiva, è possibile utilizzare il carattere =.

e la proprietà scope locale consente al consumatore di una direttiva di passare una funzione che la direttiva può invocare.

Ti preghiamo di controllare il seguente link che ti dà una chiara comprensione con esempi. L'ho trovato davvero molto utile, quindi ho pensato di condividerlo.

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


3

Anche quando l'ambito è locale, come nell'esempio, è possibile accedere all'ambito padre tramite la proprietà $parent. Supponiamo nel codice seguente, che titleè definito nell'ambito genitore. È quindi possibile accedere al titolo come $parent.title:

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

Tuttavia, nella maggior parte dei casi, lo stesso effetto si ottiene meglio usando gli attributi.

Un esempio di dove ho trovato la "&" notazione, che viene utilizzata "per passare i dati dall'ambito isolato tramite un'espressione e all'ambito padre", utile (e non è stato possibile utilizzare una banca dati bidirezionale) in una direttiva per il rendering di una speciale struttura dati all'interno di una ng-repeat.

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

Una parte del rendering era un pulsante Elimina e qui era utile collegare una funzione di eliminazione dall'ambito esterno tramite &. Sembra all'interno della direttiva render

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

Il databinding bidirezionale, ad esempio, data = "="non può essere utilizzato in quanto la funzione di eliminazione verrebbe eseguita su ogni $digestciclo, il che non va bene, poiché il record viene immediatamente cancellato e non viene mai reso.



3

la differenza principale tra loro è giusta

@ Attribute string binding
= Two-way model binding
& Callback method binding

1

@e =vedi altre risposte.

Un Gotcha su TL; DR; ottiene espressione (non funziona solo come negli esempi in altre risposte) da un genitore e la imposta come una funzione nella direttiva che chiama l'espressione. E questa funzione ha la capacità di sostituire qualsiasi variabile (anche il nome della funzione) dell'espressione, passando un oggetto con le variabili. &

&

spiegato
& è un riferimento di espressione, Questo significa che se si passa qualcosa di simile <myDirective expr="x==y"></myDirective>
nella direttiva questo exprsarà una funzione, che chiama l'espressione, come:
function expr(){return x == y}.
così nel html della direttiva <button ng-click="expr()"></button>chiamerà l'espressione. In js della direttiva $scope.expr()chiamerò anche l'espressione.
L'espressione verrà chiamata con $ scope.xe $ scope.y del padre.
Hai la possibilità di sovrascrivere i parametri!
Se le imposti per chiamata, ad esempio, <button ng-click="expr({x:5})"></button>
l'espressione verrà chiamata con il tuo parametro xe il parametro parent y.
Puoi ignorare entrambi.
Ora sai, perché <button ng-click="functionFromParent({x:5})"></button>funziona.
Perché chiama solo l'espressione del genitore (ad es<myDirective functionFromParent="function1(x)"></myDirective>) e sostituisce i possibili valori con i parametri specificati, in questo casox.
potrebbe essere:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
o
<myDirective functionFromParent="function1(x) + z"></myDirective>
con la chiamata del bambino:
<button ng-click="functionFromParent({x:5, z: 4})"></button>.
o anche con sostituzione della funzione:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>.

è solo un'espressione, non importa se è una funzione, o molte funzioni, o solo un confronto. E puoi sostituire qualsiasi variabile di questa espressione.

Esempi:
modello direttiva vs codice chiamato:
parent ha definito $ scope.x, $ scope.y:
modello parent: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>chiamate $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>chiamate 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>chiamate5 == 6

parent ha definito $ scope.function1, $ scope.x, $ scope.y:
modello parent:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>Chiamate $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>Chiamate $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>chiamate $scope.function1(5) + 6
direttiva ha $ scope.myFn in funzione:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> le chiamate$scope.myFn(5) + 6


0

Perché devo usare "{{title}}" con '@' e "title" con '='?

Quando si utilizza {{title}}, solo il valore dell'ambito padre verrà passato alla vista direttiva e valutato. Questo è limitato in un modo, il che significa che il cambiamento non si rifletterà nell'ambito padre. È possibile utilizzare '=' quando si desidera riflettere anche le modifiche apportate alla direttiva figlio all'ambito padre. Questo è a due vie.

Posso anche accedere direttamente all'ambito padre, senza decorare il mio elemento con un attributo?

Quando la direttiva contiene l'attributo scope (scope: {}), non sarà più possibile accedere direttamente all'ambito parent. Tuttavia è ancora possibile accedervi tramite scope. $ Parent ecc. Se si rimuove l'ambito dalla direttiva, è possibile accedervi direttamente.

La documentazione dice "Spesso è desiderabile passare i dati dall'ambito isolato tramite un'espressione e all'ambito padre", ma questo sembra funzionare bene anche con l'associazione bidirezionale. Perché l'espressione route sarebbe migliore?

Dipende dal contesto. Se vuoi chiamare un'espressione o una funzione con i dati, usi & e se vuoi condividere i dati, puoi usare il modo bidirezionale usando '='

Puoi trovare le differenze tra diversi modi di passare i dati alla direttiva al seguente link:

AngularJS - Mirini isolati - @ vs = vs &

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


0

@ Attributo stringa di associazione (unidirezionale) = Associazione del modello bidirezionale e associazione del metodo di callback


0

@ associa una proprietà scope locale / direttiva al valore valutato dell'attributo DOM. = associa una proprietà scope locale / direttiva a una proprietà scope padre. & associazione è per passare un metodo nell'ambito della direttiva in modo che possa essere chiamato all'interno della direttiva.

@ Attribute string binding = Binding del modello bidirezionale e metodo di callback

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.