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


He leído detenidamente la documentación de AngularJS sobre el tema y luego jugueteé con una directiva. Aquí esta la 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 también directamente al ámbito principal sin decorar mi elemento con un atributo?
  • La documentación dice "A menudo es deseable pasar datos del alcance aislado a través de una expresión y al alcance principal", pero parece funcionar bien con la unión 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/


996
2017-12-27 06:10


origen


Respuestas:


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

@ vincula una propiedad de ámbito local / directiva al valor evaluado del atributo DOM. Si utiliza title=title1 o title="title1", el valor del atributo "título" DOM ​​es simplemente la cadena title1. Si utiliza title="{{title}}", el valor del atributo "título" DOM ​​es el valor interpolado de {{title}}, por lo tanto, la cadena será cualquier propiedad de ámbito principal en la que esté "establecido" el título. Dado que los valores de los atributos siempre son cadenas, siempre terminará con un valor de cadena para esta propiedad en el alcance de la directiva al usar @.

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

Con @, puedes hacer cosas como title="{{title}} and then some" - {{title}} está interpolado, luego la cadena "y ellos algunos" se concatena con él. La cadena concatenada final es lo que obtiene la propiedad del alcance local / directivo. (No puedes hacer esto con =, solamente @.)

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

Con =, no necesita usar $ observe.

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

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

scope: { ... } 

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

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

Sí, la vinculación bidireccional permite que el alcance local / directiva y el alcance principal compartan datos. El "enlace de expresiones" 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 alcance principal, puede usar el & sintaxis.

Ver también


1109
2017-12-28 01:15



Aquí hay muchas respuestas excelentes, pero me gustaría ofrecer mi punto de vista sobre las diferencias entre @, =y & vinculante que resultó útil para mí.

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

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

  2. = el enlace es para el enlace de modelo bidireccional. El modelo en el alcance principal      está vinculado al modelo en el ámbito aislado de la directiva. Cambios a      un modelo afecta al otro, y viceversa.

  3. & vinculante es para pasar un método al alcance de su directiva para que      se puede llamar dentro de su directiva. El método está predefinido para      el alcance principal de la directiva y admite argumentos. Por ejemplo, si el método es hola (nombre) en el alcance principal, entonces en      Para ejecutar el método desde adentro de su directiva, debe      llame $ scope.hello ({name: 'world'})

Encuentro que es más fácil recordar estas diferencias al hacer referencia a los enlaces del alcance mediante una descripción más breve:

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

Los símbolos también aclaran lo que 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. &

524
2018-02-03 23:30



los = significa vinculación bidireccional, por lo que una referencia a una variable para el alcance principal. Esto significa que cuando cambie la variable en la directiva, también se cambiará en el alcance principal.

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

Por lo que sé, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane> debería funcionar también bi-title recibirá el valor de la variable del ámbito principal, que se puede cambiar en la directiva.

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


60
2017-12-27 06:20



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

36
2017-11-21 23:19



@  obtener como cadena

  • Esto no crea ningún enlace en absoluto. Simplemente está recibiendo la palabra que pasó como una cadena

=  Atasco 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 forma un poco diferente, porque el alcance obtiene una función que devuelve el objeto que se pasó en. Supongo que esto fue necesario para que funcione. El violín debería aclarar esto.

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


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


36
2017-08-26 03:40



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

  1. Alcance de los padres: Esta es la herencia de alcance predeterminada.

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

  1. Alcance del niño: directiva crea un ámbito hijo que hereda del ámbito principal si especifica la variable de ámbito de la directiva como verdadera.

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

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

Esto sucede cuando se crean complementos, ya que esto hace que la directiva sea genérica, ya que puede colocarse en cualquier HTML y no se ve afectada por su alcance principal.

Ahora, si no desea ninguna interacción con el alcance principal, entonces puede simplemente especificar el alcance 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 alcance principal, por lo que queremos que algunos de los valores / cambios pasen. 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 del 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 de alcance del controlador no se verá afectada.

@ siempre espera que el atributo mapeado sea una expresión. Esto es muy importante; porque para hacer 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 de alcance del controlador también se verá afectada

& se utiliza para vincular el método del 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 ámbito 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 sincronizar 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 enlazar al blog que lo describe muy bien.


33
2018-04-26 16:34



Simplemente podemos usar:

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

  2. = : - para el valor del objeto para el enlace de datos bidireccional. en el enlace de datos bidireccional puede cambiar el valor del alcance en la directiva y también en html.

  3. & : para métodos y funciones.

EDITAR

En nuestro Componente definición de Versión angular 1.5 Y por encima
hay cuatro tipos diferentes de enlaces:

  1. =  Encuadernación de datos bidireccional : - si cambiamos el valor, se actualiza automáticamente
  2. <  unidireccional : - cuando solo queremos leer un parámetro de un alcance principal y no actualizarlo.

  3. @ esto es para Parámetros de cadena

  4. & esto es para Devolución de llamada en caso de que su componente necesite producir algo para su alcance principal


21
2017-08-29 10:44



Creé un pequeño archivo HTML que contiene un 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>

11
2017-12-17 14:26



los = es el camino Encuadernación de 2 vías, lo que te permite tener vivir cambios dentro de su directiva. Cuando alguien cambia esa variable fuera de la directiva, tendrá esos datos modificados dentro de su directiva, pero @ camino no es unión bidireccional. Funciona como Texto. Usted se une una vez, y tendrá solo su valor.

Para entenderlo más claramente, puedes usar este excelente artículo:

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


7
2018-05-10 23:03



@ la propiedad de ámbito 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 =.

& La propiedad de alcance local permite al consumidor de una directiva pasar una función que la directiva puede invocar.

Por favor revise el enlace a continuación, que le da una comprensión clara con ejemplos. Lo encontré realmente muy útil, así que pensé en compartirlo.

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


4
2018-02-05 13:12



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

Se trata de todas las opciones:

scope:{
    name:'&'
},

scope:{
    name:'='
},

scope:{
    name:'@'
},

scope:{

},

scope:true,

https://jsfiddle.net/rishulmatta/v7xf2ujm


4
2017-12-20 06:15