¿Cuál es la diferencia entre '@' y '=' en el alcance de la directiva en AngularJS?

1067

Leí cuidadosamente la documentación de AngularJS sobre el tema, y ​​luego jugueteé con una directiva. Aquí está el violín .

Y aquí hay algunos fragmentos relevantes:

  • Del HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • De la directiva del panel:

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

Hay varias cosas que no entiendo:

  • ¿Por qué tengo que usar "{{title}}"con '@'y "title"con '='?
  • ¿Puedo acceder directamente al ámbito principal directamente, sin decorar mi elemento con un atributo?
  • La documentación dice "A menudo es deseable pasar datos del ámbito aislado a través de la expresión y al ámbito primario" , pero eso parece funcionar bien con el enlace bidireccional también. ¿Por qué la ruta de expresión sería mejor?

Encontré otro violín que también muestra la solución de expresión: http://jsfiddle.net/maxisam/QrCXh/

iwein
fuente
18
Punto justo. La capacidad de investigar y encontrar respuestas es importante.
Jonathan
1
En palabras simples, =se utiliza en el alcance de aislamiento de la directiva para habilitar el enlace bidireccional y @no actualiza el modelo, solo actualiza los valores del alcance de la Directiva.
STEEL
@iwein ¿por qué su código de violín en jsfiddle.net/maxisam/QrCXh no funciona con googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Su código solo funciona si uso su cdn
code.angularjs.org/1.0.1/angular-1.0.1.js
Veo muchas buenas respuestas a continuación, pero ¿alguien puede señalar la documentación angular oficial que responde a esta pregunta?
John Henckel

Respuestas:

1151

¿Por qué tengo que usar "{{title}}" con ' @ ' y "title" con ' = '?

@ vincula una propiedad de alcance local / directiva al valor evaluado del atributo DOM . Si usa title=title1o title="title1", el valor del atributo DOM "título" es simplemente la cadena title1. Si lo usa title="{{title}}", el valor del atributo DOM "título" es el valor interpolado de {{title}}, por lo tanto, la cadena será la propiedad de ámbito principal "título" actualmente establecida. Como los valores de los atributos son siempre cadenas, siempre terminará con un valor de cadena para esta propiedad en el alcance de la directiva cuando use @ .

= vincula una propiedad de ámbito local / directiva a una propiedad de ámbito principal . Entonces, con = , usa el nombre de la propiedad modelo / alcance principal como el valor del atributo DOM. No puedes usar {{}}s con = .

Con @, puede hacer cosas como title="{{title}} and then some": {{title}} se interpola, luego la cadena "y algunos" se concatena con ella. La cadena final concatenada es lo que obtiene la propiedad de ámbito local / directiva. (No puede hacer esto con = , solo @ .)

Con @ , deberá usarlo attr.$observe('title', function(value) { ... })si necesita usar el valor en su función de enlace (ing). Por ejemplo, if(scope.title == "...")no funcionará como esperabas. Tenga en cuenta que esto significa que solo puede acceder a este atributo de forma asincrónica . No necesita usar $ observe () si solo está usando el valor en una plantilla. Ej template: '<div>{{title}}</div>'.

Con = , no necesita usar $ observe.

¿Puedo acceder directamente al ámbito principal directamente, sin decorar mi elemento con un atributo?

Sí, pero solo si no utiliza un alcance aislado. Eliminar esta línea de su directiva

scope: { ... }

y luego su directiva no creará un nuevo alcance. Utilizará el ámbito principal. Luego puede acceder a todas las propiedades del ámbito primario directamente.

La documentación dice "A menudo es deseable pasar datos del ámbito aislado a través de una expresión y al ámbito primario", pero eso parece funcionar bien con el enlace bidireccional también. ¿Por qué la ruta de expresión sería mejor?

Sí, el enlace bidireccional permite que el ámbito local / directivo y el ámbito primario compartan datos. El "enlace de expresión" permite que la directiva invoque una expresión (o función) definida por un atributo DOM, y también puede pasar datos como argumentos a la expresión o función. Por lo tanto, si no necesita compartir datos con el padre (solo desea llamar a una función definida en el ámbito primario), puede usar la sintaxis & .

Ver también

Mark Rajcok
fuente
1
Eh, este es un comportamiento realmente extraño, especialmente cuando no se usa la interpolación y solo se trata de pasar una cadena. Aparentemente, la solicitud de extracción se ha fusionado en las compilaciones de desarrollo y está en las compilaciones 1.1.5 y 1.2.0 RC. ¡Bien por ellos para arreglar este comportamiento tan poco intuitivo!
Ibrahim
50
Escribir '@' o '=' es mucho más claro que escribir "eval-dom" o "parent-scope" o cualquier otro texto legible por humanos. Buena decisión de diseño.
Den
13
@('at') copia el valor del 'Atributo'. =('igual') es equivalente a decir que la clave es igual a su expresión. Así, al menos, así es como los mantengo firmes.
Matt DeKrey
1
¿Está seguro de que = es solo para propiedades de ámbito primario? Cualquier expresión parece funcionar, no solo las propiedades del ámbito primario.
Jonathan Aquino
44
@JonathanAquino, sí, eso funciona, pero @ sería más apropiado, con foo="{{1+1}}", porque no necesitamos enlace de datos bidireccional aquí. El punto que intenté hacer en el comentario anterior es que deberíamos usar = solo cuando la directiva necesita enlace de datos bidireccional. Use @ o & de lo contrario.
Mark Rajcok
542

Hay un montón de grandes respuestas aquí, pero me gustaría ofrecer mi punto de vista sobre las diferencias entre @, =y &vinculante que demostrado ser útil para mí.

Los tres enlaces son formas de pasar datos desde su ámbito principal al ámbito aislado de su directiva a través de los atributos del elemento:

  1. @ vinculante es para pasar cadenas. Estas cadenas admiten {{}}expresiones para valores interpolados. Por ejemplo: . La expresión interpolada se evalúa contra el alcance principal de la directiva.

  2. = enlace es para enlace de modelo de dos vías. El modelo en el ámbito principal está vinculado al modelo en el ámbito aislado de la directiva. Los cambios en un modelo afectan al otro, y viceversa.

  3. & vinculante es para pasar un método al alcance de su directiva para que pueda llamarse dentro de su directiva. El método está vinculado previamente al ámbito principal de la directiva y admite argumentos. Por ejemplo, si el método es hello (name) en el ámbito primario, entonces para ejecutar el método desde dentro de su directiva, debe llamar a $ scope.hello ({name: 'world'})

Creo que es más fácil recordar estas diferencias al referirme a los enlaces de alcance con una descripción más corta:

  • @ Enlace de cadena de atributo
  • = Encuadernación de modelo bidireccional
  • & Enlace de método de devolución de llamada

Los símbolos también aclaran qué representa la variable de alcance dentro de la implementación de su directiva:

  • @ cuerda
  • = modelo
  • & método

En orden de utilidad (para mí de todos modos):

  1. =
  2. @ @
  3. Y
bits de píxel
fuente
13
En realidad, "&"admite argumentos (o, más bien, locales) de la forma:, callback({foo: "some value"})que luego podrían usarse <my-dir callback="doSomething(foo)">. De lo contrario, buena respuesta
Nuevo Dev
11
Se debe aceptar la respuesta. Aquí hay un artículo conciso con la misma información, pero con ejemplos de código agregado: umur.io/…
Kevin
44
& NO es "Enlace de método de devolución de llamada", es enlace de expresión angular. Un ejemplo especial pero no el único es la expresión callback(argument). Que todavía no es lo mismo que callbacksí mismo.
Dmitri Zaitsev
14
Si bien me encantó cuán definitiva fue la respuesta de mayor rango, encontré que esta tuvo un impacto más útil y después de leerla entendí mucho más la respuesta anterior.
rbnzdave
1
Estoy de acuerdo con el comentario anterior, esta respuesta es más clara, definitiva y útil para la pregunta. Explica con suficiente detalle que puede ir y utilizar la información.
user3125823
64

Los =medios de unión bi-direccional, por lo que una referencia a una variable con el alcance de los padres. Esto significa que, cuando cambia la variable en la directiva, también cambiará en el ámbito primario.

@ significa que la variable se copiará (clonará) en la directiva.

Que yo sepa, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>debería funcionar también. bi-titlerecibirá el valor de la variable de ámbito principal, que se puede cambiar en la directiva.

Si necesita cambiar varias variables en el ámbito primario, puede ejecutar una función en el ámbito primario desde la directiva (o pasar datos a través de un servicio).

asgoth
fuente
1
Sí, esa parte que obtengo, veo el violín en la pregunta. Pero, ¿qué pasa con las partes que no están claras?
iwein
44
la cosa es que {{}} no funciona con =. = no se evalúa, pero la cadena se toma como el nombre de la propiedad tal como está. ¡Gracias por la respuesta!
iwein
1
No creo que = sea solo para variables en el ámbito primario. Funciona con cualquier expresión (p. Ej., 1 + 1).
Jonathan Aquino
1
@JonathanAquino tienes razón en que evalúa expresiones. En mi opinión, esto es realmente extraño y no lo usaría de esa manera. Es este tipo de trucos ingeniosos que hacen que los ámbitos de dirección sean tan difíciles de entender para mí en primer lugar.
iwein
1
¿Soy el único que piensa que esta respuesta es incorrecta! '=' significa angular espera una expresión de JavaScript y hará una asignación bidireccional si se pasa una variable de alcance. Mientras que @ mean angular espera una cadena y eso es todo. De hecho, es cierto que si usa @ en combinación con {{}} clonará el valor de la variable. ¡Pero no es la definición de @!
Luc DUZAN
39

Si desea ver más cómo funciona esto con un ejemplo en 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>"
    };
});
Juan mendez
fuente
2
Hay varios ejemplos vinculados en la pregunta y la respuesta superior. ¿Qué agrega esto?
iwein
10
@iwein, agrega claridad. Si pudiera entender y asimilar ejemplos completos, no necesitaría este sitio.
Tony Ennis
3
juan, tal vez arreglar tus errores tipográficos? 'transclude' está mal escrito. mejor aún, elimínelo (y todo lo demás, como 'reemplazar') que no contribuya directamente al problema, por lo que su solución es aún más simple y clara. +1 para el ejemplo.
Tony Ennis
gracias @AnikISlamAbhi por editar. Me gustaría contribuir más y me alegra que algunos encuentren mis muestras útiles. Ese es el objetivo principal.
Juan Mendez
Ejemplo incompleto En su demostración, está cambiando solo el valor bidireccional. Ni siquiera está tratando de cambiar el valor que tiene un alcance aislado. Por lo tanto, no demuestra adecuadamente cómo funciona el alcance en las directivas.
Sudarshan_SMD
38

@ llegar como una cuerda

  • Esto no crea ningún tipo de enlaces. Simplemente estás recibiendo la palabra que pasaste como una cadena

= Unión de 2 vías

  • Los cambios realizados desde el controlador se reflejarán en la referencia de la directiva y viceversa.

&Esto se comporta de manera un poco diferente, porque el ámbito obtiene una función que devuelve el objeto que se pasó . Supongo que esto fue necesario para que funcione. El violín debe dejar esto claro.

  • Después de llamar a esta función getter, el objeto resultante se comporta de la siguiente manera:
    • si se pasó una función : entonces la función se ejecuta en el cierre primario (controlador) cuando se llama
    • si se pasó una no función : simplemente obtenga una copia local del objeto que no tenga enlaces


Este violín debe demostrar cómo funcionan . Preste especial atención a las funciones de alcance con get...el nombre para comprender mejor lo que quiero decir sobre&

geg
fuente
36

Hay tres formas en que se puede agregar alcance en la directiva:

  1. Alcance principal : esta es la herencia de alcance predeterminada.

El alcance de la directiva y su padre (controlador / directiva dentro del cual se encuentra) es el mismo. Por lo tanto, cualquier cambio realizado en las variables de ámbito dentro de la directiva también se refleja en el controlador principal. No necesita especificar esto, ya que es el predeterminado.

  1. Ámbito secundario: la directiva crea un ámbito secundario que hereda del ámbito primario si especifica la variable de ámbito de la directiva como verdadera.

Aquí, si cambia las variables de alcance dentro de la directiva, no se reflejará en el alcance primario, pero si cambia la propiedad de una variable de alcance, eso se refleja en el alcance primario, ya que realmente modificó la variable de alcance del padre .

Ejemplo,

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. Alcance aislado : se utiliza cuando desea crear el alcance que no hereda del alcance del controlador.

Esto sucede cuando está creando complementos, ya que esto hace que la directiva sea genérica, ya que se puede colocar en cualquier HTML y no se ve afectada por su ámbito principal.

Ahora, si no desea ninguna interacción con el ámbito principal, puede especificar el ámbito como un objeto vacío. me gusta,

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

En general, este no es el caso, ya que necesitamos cierta interacción con el ámbito principal, por lo que queremos que se transmitan algunos de los valores / cambios. Por esta razón, utilizamos:

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

@ significa que los cambios desde el alcance del controlador se reflejarán en el alcance de la directiva, pero si modifica el valor en el alcance de la directiva, la variable del alcance del controlador no se verá afectada.

@ siempre espera que el atributo asignado sea una expresión. Esto es muy importante; porque para que el prefijo "@" funcione, debemos ajustar el valor del atributo dentro de {{}}.

= es bidireccional, por lo que si cambia la variable en el alcance de la directiva, la variable del alcance del controlador también se ve afectada

& se usa para vincular el método de alcance del controlador para que, si es necesario, podamos llamarlo desde la directiva

La ventaja aquí es que el nombre de la variable no necesita ser el mismo en el alcance del controlador y el alcance de la directiva.

Ejemplo, el alcance de la directiva tiene una variable "dirVar" que se sincroniza con la variable "contVar" del alcance del controlador. Esto le da mucha potencia y generalización a la directiva, ya que un controlador puede sincronizarse con la variable v1, mientras que otro controlador que usa la misma directiva puede pedirle a dirVar que se sincronice con la variable v2.

A continuación se muestra el ejemplo de uso:

La directiva y el controlador son:

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

Y el html (tenga en cuenta la diferencia para @ y =):

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

Aquí hay un enlace al blog que lo describe muy bien.

Kop4lyf
fuente
& no es "enlace de comportamiento" ni "enlace de método", es enlace de expresión angular.
Dmitri Zaitsev
20

Simplemente podemos usar: -

  1. @ : - para valores de cadena para enlace de datos unidireccional. de una manera, el enlace de datos solo puede pasar el valor del alcance a la directiva

  2. = : - para el valor del objeto para el enlace de datos bidireccional. en el enlace de datos de dos vías, puede cambiar el valor del alcance en la directiva, así como también en html.

  3. & : - para métodos y funciones.

EDITAR

En nuestra definición de Componente para la versión angular 1.5 Y arriba,
hay cuatro tipos diferentes de enlaces:

  1. = Enlace de datos bidireccional : si cambiamos el valor, se actualizará automáticamente
  2. < enlace unidireccional : cuando solo queremos leer un parámetro de un ámbito primario y no actualizarlo.

  3. @esto es para parámetros de cadena

  4. &esto es para devoluciones de llamada en caso de que su componente necesite generar algo en su ámbito primario

ojus kulkarni
fuente
13

Creé un pequeño archivo HTML que contiene código angular que demuestra las diferencias entre ellos:

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

El = camino es un enlace bidireccional , que le permite tener cambios en vivo dentro de su directiva. Cuando alguien cambia esa variable fuera de la directiva, tendrá esos datos modificados dentro de su directiva, pero @ way no es un enlace bidireccional . Funciona como texto . Atas una vez y solo tendrás su valor.

Para tenerlo más claro, puedes usar este excelente artículo:

Ámbito de la directiva AngularJS '@' y '='

Hazarapet Tunanyan
fuente
6

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 descriptionpropiedad en el ámbito secundario será el valor actual de la expresión "The movie title is {{$ctrl.movie.title}}", donde moviees 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 taglineestá inicialmente undefineden 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.

Cómo funcionan los diversos enlaces de ámbito de aislamiento

Mihail Kostira
fuente
4

La propiedad @ alcance local se utiliza para acceder a los valores de cadena que se definen fuera de la directiva.

= En los casos en que necesite crear un enlace bidireccional entre el alcance externo y el alcance aislado de la directiva, puede usar el carácter =.

Y propiedad de ámbito local permite al consumidor de una directiva pasar una función que la directiva puede invocar.

Compruebe amablemente el siguiente enlace que le brinda una comprensión clara con ejemplos. Me pareció muy útil, así que pensé en compartirlo.

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

Rafael
fuente
3

Incluso cuando el ámbito es local, como en su ejemplo, puede acceder al ámbito primario a través de la propiedad $parent. Suponga en el siguiente código, que titlese define en el ámbito primario. Luego puede acceder al título como $parent.title:

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

Sin embargo, en la mayoría de los casos, el mismo efecto se obtiene mejor utilizando atributos.

Un ejemplo de dónde encontré la notación "&", que se usa "para pasar datos del ámbito aislado a través de una expresión y al ámbito primario", útil (y no se pudo utilizar un enlace de datos bidireccional) estaba en una directiva para representar una estructura de datos especial dentro de una repetición ng.

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

Una parte de la representación fue un botón de eliminación y aquí fue útil adjuntar una función de eliminación desde el ámbito externo a través de &. Dentro de la directiva de renderización parece

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

La vinculación de datos bidireccional, es decir data = "=", no se puede utilizar, ya que la función de eliminación se ejecutaría en cada $digestciclo, lo que no es bueno, ya que el registro se elimina inmediatamente y nunca se procesa.

usuario3750988
fuente
3

Implementé todas las opciones posibles en un violín.

Se ocupa de todas las opciones:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm

Rishul Matta
fuente
3

la principal diferencia entre ellos es solo

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

@ y = ver otras respuestas.

Uno se equivocó sobre TL; DR; obtiene la expresión (no solo función como en los ejemplos en otras respuestas) de un padre, y la establece como una función en la directiva, que llama a la expresión. Y esta función tiene la capacidad de reemplazar cualquier variable (incluso el nombre de la función) de expresión, pasando un objeto con las variables. &

&

explicado
& es una referencia de expresión, eso significa que si pasa algo como <myDirective expr="x==y"></myDirective>
en la directiva, esta exprserá una función, que llama a la expresión, como:
function expr(){return x == y} .
entonces, en la directiva, html <button ng-click="expr()"></button>llamará a la expresión. En js de la directiva solo $scope.expr()llamaremos a la expresión también.
Se llamará a la expresión con $ scope.x y $ scope.y del padre.
¡Tienes la capacidad de anular los parámetros!
Si los configura por llamada, por ejemplo <button ng-click="expr({x:5})"></button>
, la expresión se llamará con su parámetro xy el parámetro principal y.
Puedes anular ambos.
Ahora ya sabes, por qué <button ng-click="functionFromParent({x:5})"></button>funciona.
Porque solo llama a la expresión de padre (p. Ej.<myDirective functionFromParent="function1(x)"></myDirective>) y reemplaza los posibles valores con los parámetros especificados, en este caso x.
podría ser:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
o
<myDirective functionFromParent="function1(x) + z"></myDirective>
con el llamado niño:
<button ng-click="functionFromParent({x:5, z: 4})"></button>.
o incluso con el reemplazo de la función:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>.

es solo una expresión, no importa si es una función, o muchas funciones, o simplemente una comparación. Y puede reemplazar cualquier variable de esta expresión.

Ejemplos:
plantilla de directiva frente a código llamado:
padre ha definido $ scope.x, $ scope.y:
plantilla padre: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>llamadas $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>llamadas 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>llamadas5 == 6

padre ha definido $ scope.function1, $ scope.x, $ scope.y:
plantilla padre:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>Llamadas $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>Llamadas $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>llamadas $scope.function1(5) + 6
Directiva tiene como función $ scope.myFn:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> llamadas$scope.myFn(5) + 6

ya_dimon
fuente
0

¿Por qué tengo que usar "{{title}}" con '@' y "title" con '='?

Cuando usa {{title}}, solo el valor del alcance principal se pasará a la vista directiva y se evaluará. Esto se limita a un solo sentido, lo que significa que el cambio no se reflejará en el ámbito principal. Puede usar '=' cuando desee reflejar los cambios realizados en la directiva secundaria al ámbito primario también. Esto es de dos vías.

¿Puedo acceder directamente al ámbito principal directamente, sin decorar mi elemento con un atributo?

Cuando la directiva tiene un atributo de alcance (alcance: {}), ya no podrá acceder directamente al alcance principal. Pero aún así es posible acceder a él a través de scope. $ Parent, etc. Si elimina el alcance de la directiva, se puede acceder directamente.

La documentación dice "A menudo es deseable pasar datos del ámbito aislado a través de una expresión y al ámbito primario", pero eso parece funcionar bien con el enlace bidireccional también. ¿Por qué la ruta de expresión sería mejor?

Depende del contexto. Si desea llamar a una expresión o función con datos, use & y si desea compartir datos, puede usar la forma bidireccional usando '='

Puede encontrar las diferencias entre varias formas de pasar datos a la directiva en el siguiente enlace:

AngularJS - Ámbitos aislados - @ vs = vs &

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

Prashanth
fuente
0

@ Enlace de cadena de atributo (unidireccional) = Enlace de modelo bidireccional y enlace de método de devolución de llamada

Jatin Patel
fuente
0

@ vincula una propiedad de ámbito local / directiva al valor evaluado del atributo DOM. = vincula una propiedad de ámbito local / directiva a una propiedad de ámbito principal. & vinculante es para pasar un método al alcance de su directiva para que pueda llamarse dentro de su directiva.

@ Enlace de cadena de atributo = Enlace de modelo bidireccional y enlace de método de devolución de llamada

Ashish Kamble
fuente