Qual è la differenza tra “@” e “=” nell’ambito della direttiva in AngularJS?

Ho letto attentamente la documentazione di AngularJS sull’argomento e poi mi sono occupato di una direttiva. Ecco il violino .

E qui ci sono alcuni frammenti rilevanti:

  • Dall’HTML:

    {{text}} 
  • Dalla direttiva del riquadro:

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

Ci sono molte cose che non capisco:

  • Perché devo usare "{{title}}" con '@' e "title" con '=' ?
  • Posso accedere direttamente allo scope genitore, senza decorare il mio elemento con un attributo?
  • La documentazione dice “Spesso è desiderabile passare dati dall’ambito isolato tramite un’espressione e l’ambito genitore” , ma sembra funzionare bene anche con il bind bidirezionale. Perché la via dell’espressione dovrebbe essere migliore?

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

Perché devo usare “{{title}}” con ” @ ” e “title” con ” = “?

@ associa una proprietà scope locale / direttiva al valore valutato dell’attributo DOM . Se si utilizza title=title1 o 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à qualsiasi proprietà dell’ambito genitore “title” è attualmente impostata su. Dato che i valori degli attributi sono sempre stringhe, quando si utilizza @ viene sempre incluso un valore di stringa per questa proprietà nell’ambito della direttiva.

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

Con @, puoi fare cose come title="{{title}} and then some" – {{title}} è interpolato, quindi la stringa “e loro alcuni” è concatenata con esso. La stringa concatenata finale è ciò che ottiene la proprietà scope locale / direttiva. (Non puoi farlo con = , solo @ .)

Con @ , dovrai usare attr.$observe('title', function(value) { ... }) se hai bisogno di usare il valore nella tua funzione link (ing). Ad esempio, if(scope.title == "...") non funzionerà come previsto. Nota che questo significa che puoi accedere a questo attributo in modo asincrono . Non è necessario utilizzare $ observ () se si utilizza solo il valore in un modello. Ad esempio, template: '

{{title}}

' .

Con = , non è necessario utilizzare $ observ.

Posso accedere direttamente allo scope genitore, 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 genitore. È quindi ansible accedere direttamente a tutte le proprietà dell’ambito principale.

La documentazione dice “Spesso è desiderabile passare dati dall’ambito isolato tramite un’espressione e l’ambito genitore”, ma sembra funzionare bene anche con il bind bidirezionale. Perché la via dell’espressione dovrebbe essere migliore?

Sì, l’associazione bidirezionale consente all’ambito locale / direttiva e all’ambito principale di condividere i dati. “Expression binding” consente alla direttiva di chiamare un’espressione (o funzione) definita da un attributo DOM e inoltre è ansible passare i dati come argomenti all’espressione o alla funzione. Quindi, se non hai bisogno di condividere i dati con il genitore – vuoi solo chiamare una funzione definita nell’ambito genitore – puoi usare la syntax & .

Guarda anche

  • Post del blog di Lukas per l’ambito isolato (covers @, =, &)
  • la spiegazione di dnc253 su @ e =
  • la mia risposta al blog sugli ambiti – la sezione delle direttive (in basso, appena prima della sezione Sommario) ha un’immagine di un ambito isolato e il suo ambito genitore – l’ambito direttiva usa @ per una proprietà e = per un’altra
  • Qual è la differenza tra & vs @ e = in angularJS

Ci sono molte grandi risposte qui, ma vorrei offrire la mia prospettiva sulle differenze tra @ , = e vincolanti che si sono rivelate utili per me.

Tutti e tre i collegamenti sono modi per trasferire i dati dall’ambito principale all’ambito isolato della direttiva attraverso gli attributi dell’elemento:

  1. @ binding è per passare stringhe. Queste stringhe supportano le espressioni {{}} per i valori interpolati. Per esempio: . L’espressione interpolata viene valutata rispetto all’ambito principale della direttiva.

  2. = il legame è per il bind modello a due vie. Il modello nell’object principale è collegato al modello nell’ambito isolato della direttiva. Le modifiche a un modello influiscono sull’altro e viceversa.

  3. & binding è per passare un metodo nell’ambito della tua direttiva in modo che possa essere chiamato all’interno della tua direttiva. Il metodo è pre-associato all’ambito padre della direttiva e supporta gli argomenti. Ad esempio, se il metodo è hello (nome) nell’object principale, per eseguire il metodo dall’interno della direttiva, è necessario chiamare $ scope.hello ({name: ‘world’})

Trovo che sia più facile ricordare queste differenze facendo riferimento ai collegamenti degli scope con una descrizione più breve:

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

I simboli rendono anche più chiaro ciò che la variabile scope rappresenta all’interno dell’implementazione della tua direttiva:

  • @ stringa
  • = modello
  • & metodo

In ordine di utilità (per me comunque):

  1. =
  2. @
  3. &

Il = significa associazione bidirezionale, quindi un riferimento a una variabile per l’ambito genitore. Ciò significa che quando si modifica la variabile nella direttiva, verrà modificata anche nell’ambito genitore.

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

Per quanto ne so, {{text}} dovrebbe funzionare anche. bi-title riceverà il valore della variabile scope genitore, che può essere modificato nella direttiva.

Se è necessario modificare più variabili nell’ambito genitore, è ansible eseguire una funzione nell’ambito genitore dall’interno della direttiva (o passare i dati tramite un servizio).

Se vuoi vedere di più su 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: "

{{title1}} {{title2}}

" }; });

@ prendi come stringa

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

= 2 vie

  • le modifiche apportate dal controller si rifletteranno nel riferimento contenuto nella direttiva e viceversa

& Ciò si comporta in modo leggermente diverso, perché l’oscilloscopio ottiene una funzione che restituisce l’object che è stato passato . Suppongo che fosse necessario per farlo funzionare. Il violino dovrebbe chiarirlo.

  • Dopo aver chiamato questa funzione getter, l’object risultante si comporta come segue:
    • se è stata passata una funzione : allora la funzione viene eseguita nella chiusura genitore (controllore) quando viene chiamata
    • se è stata inoltrata una non funzione : è sufficiente ottenere una copia locale dell’object che non ha associazioni

Questo violino dovrebbe dimostrare come funzionano . Presta particolare attenzione alle funzioni dell’ambito con get... nel nome per sperare di capire meglio cosa intendo riguardo &

Ci sono tre modi in cui è ansible aggiungere un ambito alla direttiva:

  1. Ambito genitore : si tratta dell’ereditarietà dell’ambito predefinita.

La direttiva e il suo ambito genitore (controller / direttiva all’interno del quale giace) sono gli stessi. Quindi tutte le modifiche apportate alle variabili dell’ambito all’interno della direttiva si riflettono anche nel controller principale. Non è necessario specificarlo poiché è l’impostazione predefinita.

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

Qui, se si modificano le variabili dell’ambito all’interno della direttiva, essa non si rifletterà nello scope genitore, ma se si modifica la proprietà di una variabile scope, questa viene riflessa nell’object genitore, poiché si modificava effettivamente la variabile scope dell’elemento genitore .

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

Questo accade quando si creano plug-in poiché questo rende la direttiva generica poiché può essere inserita in qualsiasi HTML e non viene influenzata dall’ambito principale.

Ora, se non vuoi alcuna interazione con l’ambito genitore, puoi semplicemente specificare l’ambito come un object vuoto. piace,

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

Principalmente questo non è il caso in quanto abbiamo bisogno di una certa interazione con l’ambito genitore, quindi vogliamo che alcuni dei valori / cambiamenti siano passati. Per questo motivo, usiamo:

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

@ significa 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 all’interno di {{}}.

= è bidirezionale, quindi se si modifica la variabile in ambito direttiva, anche la variabile dell’ambito del controller viene influenzata

& è usato per bind il metodo dell’ambito del controllore in modo che, se necessario, possiamo chiamarlo dalla direttiva

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

Esempio, l’ambito 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 controllore 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 (notare la differnce per @ e =):

 

Ecco un link al blog che lo descrive bene.

Semplicemente possiamo usare: –

  1. @ : – per i valori stringa per l’associazione dati in un modo. in un modo di associazione dati è ansible solo passare il valore di ambito alla direttiva

  2. = : – per il valore dell’object per l’associazione dati bidirezionale. in associazione bidirezionale dei dati è ansible modificare anche il valore dell’ambito in direttiva e anche in html.

  3. & : – per metodi e funzioni.

MODIFICARE

Nella nostra definizione di componente per Angular versione 1.5 E sopra
ci sono quattro diversi tipi di attacchi:

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

  3. @ questo è per i parametri stringa

  4. & questo è per Callback nel caso in cui il tuo componente abbia bisogno di produrre qualcosa per il suo genitore

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

    Angular        

The = way è l’ associazione a 2 vie , che ti consente di avere modifiche live all’interno della tua direttiva. Quando qualcuno cambia quella variabile di direttiva, avrai i dati modificati all’interno della direttiva, ma @ way non è bind a due vie . Funziona come il testo . Ti leghi una volta e avrai solo il suo valore.

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

Ambito della direttiva AngularJS ‘@’ e ‘=’

La proprietà @ scope locale viene utilizzata per accedere ai valori stringa definiti all’esterno della direttiva.

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

La proprietà & scope locale consente al consumatore di una direttiva di passare in una funzione che la direttiva può richiamare.

Si prega di controllare il link qui sotto 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

Ho implementato tutte le opzioni possibili in un violino.

Si occupa di tutte le opzioni:

 scope:{ name:'&' }, scope:{ name:'=' }, scope:{ name:'@' }, scope:{ }, scope:true, 

https://jsfiddle.net/rishulmatta/v7xf2ujm

Anche quando l’ambito è locale, come nel tuo esempio, puoi accedere all’ambito genitore attraverso la proprietà $parent . Supponiamo che nel codice sottostante, tale title sia definito nell’ambito genitore. Puoi quindi 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 è ottenuto meglio usando gli attributi.

Un esempio di dove ho trovato la notazione “&”, che è usata “per passare dati dall’ambito isolato tramite un’espressione e all’ambito genitore”, era utile (e un databinding bidirezionale non poteva essere usato) in una direttiva per il rendering di una datastruttura speciale all’interno di una ng-repeat.

   

Una parte del rendering era un pulsante di cancellazione e qui era utile colbind una funzione di eliminazione dall’ambito esterno tramite &. All’interno della direttiva di rendering sembra

 scope : { data = "=", deleteFunction = "&"}, template : "... " 

L’associazione data = "=" bidirezionale cioè data = "=" non può essere utilizzata poiché la funzione di eliminazione verrebbe eseguita su ogni ciclo $digest , il che non è buono, poiché il record viene immediatamente eliminato e mai reso.

@ e = vedi altre risposte.

Una cosa su &
TL; DR;
& ottiene espressione (non solo funziona come negli esempi in altre risposte) da un genitore, e lo 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) di espressione, passando un object con le variabili.

ha spiegato
& è un’espressione di riferimento, ovvero se passi qualcosa come
nella direttiva questo expr sarà una funzione, che chiama l’espressione, come:
function expr(){return x == y} .
quindi in html della direttiva chiamerà l’espressione. In js della direttiva, solo $scope.expr() chiamerà anche l’espressione.
L’espressione verrà chiamata con $ scope.x e $ scope.y del genitore.
Hai la possibilità di sovrascrivere i parametri!
Se li imposti per chiamata, ad esempio
quindi l’espressione verrà chiamata con il parametro x e il parametro parent y .
È ansible ignorare entrambi.
Ora sai, perché funziona.
Perché chiama solo l’espressione di genitore (ad esempio ) e sostituisce i possibili valori con i parametri specificati, in questo caso x .
potrebbe essere:

o

con chiamata bambino:
.
o anche con la sostituzione della funzione:
.

è 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 di direttiva vs codice chiamato:
genitore ha definito $ scope.x, $ scope.y:
modello principale:
chiama $scope.x==$scope.y
chiama 5 == $scope.y
chiama 5 == 6

genitore ha definito $ scope.function1, $ scope.x, $ scope.y:
modello principale:

chiama $scope.function1($scope.x) + $scope.y
chiama $scope.function1(5) + $scope.y
chiama $scope.function1(5) + 6
direttiva ha $ scope.myFn come funzione:
chiama $scope.myFn(5) + 6

la principale differenza tra loro è giusta

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

Perché devo usare “{{title}}” con “@” e “title” con “=”?

Quando si utilizza {{title}}, solo il valore dell’ambito genitore verrà passato alla vista direttiva e valutato. Questo è limitato a un modo, il che significa che il cambiamento non si rifletterà nello scope principale. È ansible utilizzare ‘=’ quando si desidera riflettere anche le modifiche apportate nella direttiva figlio all’ambito padre. Questo è a due vie.

Posso accedere direttamente allo scope genitore, senza decorare il mio elemento con un attributo?

Quando la direttiva ha attributo scope (scope: {}), allora non sarà più ansible accedere direttamente all’ambito genitore. Ma è ancora ansible accedervi tramite scope. $ Parent etc. Se si rimuove scope da direttiva, è ansible accedervi direttamente.

La documentazione dice “Spesso è desiderabile passare dati dall’ambito isolato tramite un’espressione e l’ambito genitore”, ma sembra funzionare bene anche con il bind bidirezionale. Perché la via dell’espressione dovrebbe essere migliore?

Dipende dal contesto. Se si desidera chiamare un’espressione o una funzione con dati, si utilizza & e se si desidera condividere i dati, è ansible utilizzare la modalità di biderection utilizzando ‘=’

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

AngularJS – Scopes isolati – @ vs = vs &

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

@ Assegnazione di stringhe di attributi (solo andata) = Associazione di modelli a due vie e Associazione del metodo di callback

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

@ Vincolo stringa attributo = Associazione modello a due vie e Associazione metodo callback