Esta pregunta ya ha sido golpeada hasta la muerte, pero la compartiré de todos modos en caso de que alguien más esté luchando con el horrible desastre que es el alcance de AngularJS. Esta cubierta =
, <
, @
, &
y ::
. La redacción completa se puede encontrar aquí .
=
establece un enlace bidireccional. Cambiar la propiedad en el padre dará como resultado un cambio en el hijo, y viceversa.
<
establece un enlace unidireccional, de padre a hijo. Cambiar la propiedad en el padre dará como resultado un cambio en el hijo, pero cambiar la propiedad del hijo no afectará la propiedad del padre.
@
asignará a la propiedad secundaria el valor de cadena del atributo de etiqueta. Si el atributo contiene una expresión , la propiedad secundaria se actualiza cada vez que la expresión se evalúa en una cadena diferente. Por ejemplo:
<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
description: '@',
}
Aquí, la description
propiedad en el ámbito secundario será el valor actual de la expresión "The movie title is {{$ctrl.movie.title}}"
, donde movie
es un objeto en el ámbito primario.
&
es un poco complicado, y de hecho no parece haber ninguna razón convincente para usarlo. Le permite evaluar una expresión en el ámbito primario, sustituyendo parámetros con variables del ámbito secundario. Un ejemplo ( 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'
}
});
Dado parentVar=10
, la expresión parentFoo({myVar:5, myOtherVar:'xyz'})
se evaluará 5 + 10 + 'xyz'
y el componente se representará como:
<div>15xyz</div>
¿Cuándo querrías usar esta funcionalidad enrevesada? &
A menudo la gente lo utiliza para pasar al ámbito secundario una función de devolución de llamada en el ámbito primario. En realidad, sin embargo, se puede lograr el mismo efecto usando '<' para pasar la función, que es más sencilla y evita la incómoda sintaxis de llaves para pasar parámetros ( {myVar:5, myOtherVar:'xyz'}
). Considerar:
Devolución de llamada utilizando &
:
<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: '&'
}
});
Devolución de llamada utilizando <
:
<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: '<'
}
});
Tenga en cuenta que los objetos (y las matrices) se pasan por referencia al ámbito secundario, no se copian. Lo que esto significa es que, incluso si se trata de un enlace unidireccional, está trabajando con el mismo objeto en el ámbito primario y secundario.
Para ver los diferentes prefijos en acción, abra este plunk .
Enlace único (inicialización) usando
::
[Documentos oficiales]
Las versiones posteriores de AngularJS introducen la opción de tener un enlace de una sola vez, donde la propiedad del ámbito secundario se actualiza solo una vez. Esto mejora el rendimiento al eliminar la necesidad de vigilar la propiedad principal. La sintaxis es diferente de la anterior; para declarar un enlace de una sola vez, agregue ::
delante de la expresión en la etiqueta del componente :
<child-component
tagline = "::$ctrl.tagline">
</child-component>
Esto propagará el valor del tagline
ámbito secundario sin establecer un enlace unidireccional o bidireccional. Nota : si tagline
está inicialmente undefined
en el ámbito primario, angular lo observará hasta que cambie y luego realizará una actualización única de la propiedad correspondiente en el ámbito secundario.
Resumen
La siguiente tabla muestra cómo funcionan los prefijos dependiendo de si la propiedad es un objeto, matriz, cadena, etc.