Respuestas:
@
permite que un valor definido en el atributo de directiva se pase al ámbito de aislamiento de la directiva. El valor podría ser un valor de cadena simple ( myattr="hello"
) o podría ser una cadena interpolada AngularJS con expresiones incrustadas ( myattr="my_{{helloText}}"
). Piense en ello como una comunicación "unidireccional" desde el alcance de los padres hacia la directiva del niño. John Lindquist tiene una serie de videos cortos que explican cada uno de estos. Screencast en @ está aquí: https://egghead.io/lessons/angularjs-isolate-scope-attribute-binding
&
permite que el ámbito de aislamiento de la directiva pase valores al ámbito principal para su evaluación en la expresión definida en el atributo. Tenga en cuenta que el atributo directivo es implícitamente una expresión y no utiliza la sintaxis de expresión de doble llave. Este es más difícil de explicar en el texto. Screencast en y está aquí: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding
=
configura una expresión de enlace bidireccional entre el ámbito de aislamiento de la directiva y el ámbito primario. Los cambios en el ámbito secundario se propagan al padre y viceversa. Piense en = como una combinación de @ y &. Screencast on = está aquí: https://egghead.io/lessons/angularjs-isolate-scope-two-way-binding
Y finalmente aquí hay un screencast que muestra los tres utilizados juntos en una sola vista: https://egghead.io/lessons/angularjs-isolate-scope-review
Me gustaría explicar los conceptos desde la perspectiva de la herencia del prototipo de JavaScript. Con suerte ayuda a entender.
Hay tres opciones para definir el alcance de una directiva:
scope: false
: Predeterminado angular. El alcance de la directiva es exactamente el de su alcance padre ( parentScope
).scope: true
: Angular crea un ámbito para esta directiva. El alcance hereda prototípicamente de parentScope
.scope: {...}
: el alcance aislado se explica a continuación. Especificar scope: {...}
define un isolatedScope
. An isolatedScope
no hereda propiedades de parentScope
, aunque isolatedScope.$parent === parentScope
. Se define a través de:
app.directive("myDirective", function() {
return {
scope: {
... // defining scope means that 'no inheritance from parent'.
},
}
})
isolatedScope
no tiene acceso directo a parentScope
. Pero a veces la directiva necesita comunicarse con el parentScope
. Se comunican a través de @
, =
y &
. El tema sobre el uso de los símbolos @
, =
y &
estamos hablando de escenarios utilizandoisolatedScope
.
Por lo general, se usa para algunos componentes comunes compartidos por diferentes páginas, como Modals. Un alcance aislado evita contaminar el alcance global y es fácil de compartir entre páginas.
Aquí hay una directiva básica: http://jsfiddle.net/7t984sf9/5/ . Una imagen para ilustrar es:
@
: enlace unidireccional@
simplemente pasa la propiedad de parentScope
a isolatedScope
. Se llama one-way binding
, lo que significa que no puede modificar el valor de las parentScope
propiedades. Si está familiarizado con la herencia de JavaScript, puede comprender estos dos escenarios fácilmente:
Si la propiedad de enlace es un tipo primitivo, como interpolatedProp
en el ejemplo: puede modificar interpolatedProp
, pero parentProp1
no se cambiaría. Sin embargo, si cambia el valor de parentProp1
, interpolatedProp
se sobrescribirá con el nuevo valor (cuando angular $ digest).
Si la propiedad de enlace es algún objeto, como parentObj
: dado que el que se pasa isolatedScope
es una referencia, la modificación del valor activará este error:
TypeError: Cannot assign to read only property 'x' of {"x":1,"y":2}
=
: enlace bidireccional=
se llama two-way binding
, lo que significa que cualquier modificación en childScope
también actualizará el valor en parentScope
, y viceversa. Esta regla funciona tanto para primitivos como para objetos. Si cambia el tipo de enlace de parentObj
ser =
, verá que puede modificar el valor de parentObj.x
. Un ejemplo típico es ngModel
.
&
: enlace de función&
permite que la directiva llame a alguna parentScope
función y pase algún valor de la directiva. Por ejemplo, marque JSFiddle: & en el alcance de la directiva .
Defina una plantilla cliqueable en la directiva como:
<div ng-click="vm.onCheck({valueFromDirective: vm.value + ' is from the directive'})">
Y usa la directiva como:
<div my-checkbox value="vm.myValue" on-check="vm.myFunction(valueFromDirective)"></div>
La variable valueFromDirective
se pasa de la directiva al controlador principal a través de {valueFromDirective: ...
.
Referencia: Comprender los ámbitos
No es mi violín, pero http://jsfiddle.net/maxisam/QrCXh/ muestra la diferencia. La pieza clave es:
scope:{
/* NOTE: Normally I would set my attributes and bindings
to be the same name but I wanted to delineate between
parent and isolated scope. */
isolatedAttributeFoo:'@attributeFoo',
isolatedBindingFoo:'=bindingFoo',
isolatedExpressionFoo:'&'
}
@ : enlace unidireccional
= : enlace bidireccional
& : enlace de función
AngularJS - Ámbitos aislados - @ vs = vs &
Ejemplos breves con explicación están disponibles en el siguiente enlace:
http://www.codeforeach.com/angularjs/angularjs-isolated-scopes-vs-vs
@ - enlace unidireccional
En directiva:
scope : { nameValue : "@name" }
En vista:
<my-widget name="{{nameFromParentScope}}"></my-widget>
= - enlace bidireccional
En directiva:
scope : { nameValue : "=name" },
link : function(scope) {
scope.name = "Changing the value here will get reflected in parent scope value";
}
En vista:
<my-widget name="{{nameFromParentScope}}"></my-widget>
& - Llamada de función
En directiva:
scope : { nameChange : "&" }
link : function(scope) {
scope.nameChange({newName:"NameFromIsolaltedScope"});
}
En vista:
<my-widget nameChange="onNameChange(newName)"></my-widget>
Me llevó muchísimo tiempo entender realmente esto. La clave para mí fue comprender que "@" es para cosas que desea evaluar in situ y pasar a la directiva como una constante donde "=" realmente pasa el objeto en sí.
Hay una buena publicación de blog que explica esto en: http://blog.ramses.io/technical/AngularJS-the-difference-between-@-&-and-=-when-declaring-directives-using-isolate-scopes