Question Quelle est la différence entre '@' et '=' dans la portée de la directive dans AngularJS?


J'ai lu attentivement la documentation d'AngularJS sur le sujet, puis j'ai trituré une directive. Ici se trouve le violon.

Et voici quelques extraits pertinents:

  • Du HTML:

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
    
  • De la directive du volet:

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

Il y a plusieurs choses que je ne comprends pas:

  • Pourquoi dois-je utiliser "{{title}}" avec '@' et "title" avec '='?
  • Puis-je également accéder directement à la portée parent sans décorer mon élément avec un attribut?
  • La documentation dit "Souvent, il est souhaitable de transmettre des données de la portée isolée via une expression et à la portée parent", mais cela semble fonctionner correctement avec la liaison bidirectionnelle aussi. Pourquoi la voie d'expression serait-elle meilleure?

J'ai trouvé un autre violon qui montre aussi la solution d'expression: http://jsfiddle.net/maxisam/QrCXh/


996
2017-12-27 06:10


origine


Réponses:


Pourquoi dois-je utiliser "{{title}}" avec '@'et "titre" avec'='?

@ lie une propriété d'étendue locale / directive au valeur évaluée de l'attribut DOM. Si tu utilises title=title1 ou title="title1", la valeur de l'attribut DOM "title" est simplement la chaîne title1. Si tu utilises title="{{title}}", la valeur de l'attribut DOM "title" est la valeur interpolée de {{title}}Par conséquent, la chaîne sera la propriété de portée parent "title" actuellement définie. Comme les valeurs d'attribut sont toujours des chaînes, vous obtiendrez toujours une valeur de chaîne pour cette propriété dans la portée de la directive lorsque vous utilisez @.

= lie une propriété d'étendue locale / directive à une propriété de portée parent. Donc avec =, vous utilisez le nom de la propriété parent modèle / scope comme valeur de l'attribut DOM. Vous ne pouvez pas utiliser {{}}s avec =.

Avec @, vous pouvez faire des choses comme title="{{title}} and then some" - {{title}} est interpolé, puis la chaîne "et les uns" est concaténée avec. La chaîne concaténée finale est ce que la propriété d'étendue locale / directive obtient. (Vous ne pouvez pas faire cela avec =, seulement @.)

Avec @, vous devrez utiliser attr.$observe('title', function(value) { ... }) si vous avez besoin d'utiliser la valeur dans votre fonction link (ing). Par exemple., if(scope.title == "...") ne fonctionnera pas comme prévu. Notez que cela signifie que vous ne pouvez accéder qu'à cet attribut asynchrone. Vous n'avez pas besoin d'utiliser $ observe () si vous utilisez uniquement la valeur dans un modèle. Par exemple., template: '<div>{{title}}</div>'.

Avec =, vous n'avez pas besoin d'utiliser $ observe.

Puis-je également accéder directement à la portée parent sans décorer mon élément avec un attribut?

Oui, mais seulement si vous n'utilisez pas une portée isolate. Supprimer cette ligne de votre directive

scope: { ... } 

et votre directive ne créera pas de nouvelle portée. Il utilisera la portée parent. Vous pouvez ensuite accéder directement à toutes les propriétés de portée parent.

La documentation dit «Souvent, il est souhaitable de transmettre des données de la portée isolée via une expression et à la portée parent», mais cela semble fonctionner correctement avec la liaison bidirectionnelle. Pourquoi la voie d'expression serait-elle meilleure?

Oui, la liaison bidirectionnelle permet à la portée locale / directive et à la portée parent de partager des données. La "liaison d'expression" permet à la directive d'appeler une expression (ou une fonction) définie par un attribut DOM - et vous pouvez également transmettre des données en tant qu'arguments à l'expression ou à la fonction. Donc, si vous n'avez pas besoin de partager des données avec le parent - vous voulez juste appeler une fonction définie dans la portée parent - vous pouvez utiliser le & syntaxe.

Voir également


1109
2017-12-28 01:15



Il y a beaucoup de bonnes réponses ici, mais je voudrais offrir mon point de vue sur les différences entre @, =, et & contraignant qui s'est avéré utile pour moi.

Les trois liaisons permettent de transmettre des données de votre périmètre parent à la portée isolée de votre directive via les attributs de l'élément:

  1. @ la liaison est pour passer des chaînes.      Ces chaînes supportent {{}} expressions pour les valeurs interpolées.      Par exemple:      . L'expression interpolée est évaluée par rapport à      portée parent de la directive.

  2. = la liaison est pour la liaison du modèle bidirectionnel. Le modèle dans la portée parentale      est lié au modèle dans le champ d'application isolé de la directive. Changements à      un modèle affecte l'autre, et vice versa.

  3. & liaison est pour passer une méthode dans le champ d'application de votre directive afin que      cela peut être appelé dans votre directive. La méthode est pré-liée à      la portée parent de la directive et prend en charge les arguments. Par exemple si la méthode est bonjour (nom) dans la portée parent, alors dans      afin d'exécuter la méthode à l'intérieur de votre directive, vous devez      appelez $ scope.hello ({name: 'world'})

Je trouve qu'il est plus facile de se souvenir de ces différences en se référant aux liaisons de portée par une description plus courte:

  • @  Liaison de chaîne d'attribut
  • =  Liaison de modèle à deux voies
  • &  Méthode de rappel contraignante

Les symboles clarifient également la signification de la variable scope dans l'implémentation de votre directive:

  • @  chaîne
  • =  modèle
  • &  méthode

Par ordre d'utilité (pour moi de toute façon):

  1. =
  2. @
  3. &

524
2018-02-03 23:30



le = signifie liaison bidirectionnelle, donc une référence à une variable à la portée parent. Cela signifie que lorsque vous modifiez la variable dans la directive, elle sera également modifiée dans la portée parent.

@ signifie que la variable sera copiée (clonée) dans la directive.

Pour autant que je sache, <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane> devrait travailler aussi. bi-title recevra la valeur de variable d'étendue parent, qui peut être modifiée dans la directive.

Si vous devez modifier plusieurs variables dans la portée parente, vous pouvez exécuter une fonction sur la portée parent à partir de la directive (ou transmettre des données via un service).


60
2017-12-27 06:20



Si vous souhaitez voir plus comment cela fonctionne avec un exemple en direct. 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



@  obtenir comme chaîne

  • Cela ne crée aucune liaison. Vous obtenez simplement le mot que vous avez passé en tant que chaîne

=  Reliure à 2 voies

  • les modifications apportées par le contrôleur seront reflétées dans la référence détenue par la directive, et vice-versa

&Cela se comporte un peu différemment, car la portée obtient une fonction qui renvoie l'objet qui a été transmis. Je suppose que c'était nécessaire pour que ça marche. Le violon devrait le rendre clair.

  • Après avoir appelé cette fonction getter, l'objet résultant se comporte comme suit:
    • si un fonction a été passé: alors la fonction est exécutée dans la fermeture parent (contrôleur) lorsqu'elle est appelée
    • si un non-fonction a été transmis: il suffit d'obtenir une copie locale de l'objet qui n'a aucune liaison


Ce violon devrait montrer comment ils fonctionnent. Portez une attention particulière aux fonctions de portée avec get... au nom de mieux comprendre ce que je veux dire à propos de &


36
2017-08-26 03:40



Il y a trois façons d'ajouter de la portée dans la directive:

  1. Portée parentale: Il s'agit de l'héritage de portée par défaut.

La directive et son parent (contrôleur / directive à l'intérieur duquel elle repose) sont identiques. Ainsi, toutes les modifications apportées aux variables d'étendue à l'intérieur de la directive sont également répercutées dans le contrôleur parent. Vous n'avez pas besoin de le spécifier car c'est la valeur par défaut.

  1. Portée enfant: directive crée une portée enfant qui hérite de la portée parent si vous spécifiez la variable scope de la directive comme true.

Ici, si vous modifiez les variables de portée à l'intérieur de la directive, elles ne refléteront pas dans la portée parente, mais si vous modifiez la propriété d'une variable de portée, cela est reflété dans la portée parent, puisque vous avez modifié la variable de portée du parent .

Exemple,

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. Portée isolée: Ceci est utilisé lorsque vous voulez créer la portée qui n'hérite pas de la portée du contrôleur.

Cela se produit lorsque vous créez des plugins car cela rend la directive générique car elle peut être placée dans n'importe quel HTML et n'est pas affectée par sa portée parent.

Maintenant, si vous ne voulez pas d'interaction avec la portée parent, vous pouvez simplement spécifier la portée en tant qu'objet vide. comme,

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

Dans la plupart des cas, ce n'est pas le cas car nous avons besoin d'une certaine interaction avec la portée parentale, nous voulons donc que certaines des valeurs / modifications passent. Pour cette raison, nous utilisons:

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

@ signifie que les changements de la portée du contrôleur seront reflétés dans la portée de la directive, mais si vous modifiez la valeur dans la portée de la directive, la variable de portée du contrôleur ne sera pas affectée.

@ attend toujours que l'attribut mappé soit une expression. C'est très important; car pour que le préfixe "@" fonctionne, nous devons placer la valeur de l'attribut dans {{}}.

= est bidirectionnel, donc si vous changez la variable dans la portée de la directive, la variable de portée du contrôleur est affectée aussi

& est utilisé pour lier la méthode de portée du contrôleur de sorte que si nécessaire, nous pouvons l'appeler à partir de la directive

L'avantage ici est que le nom de la variable n'a pas besoin d'être le même dans la portée du contrôleur et la portée de la directive.

Exemple, la portée de la directive a une variable "dirVar" qui se synchronise avec la variable "contVar" de la portée du contrôleur. Cela donne beaucoup de puissance et de généralisation à la directive car un contrôleur peut se synchroniser avec la variable v1 tandis qu'un autre contrôleur utilisant la même directive peut demander à dirVar de se synchroniser avec la variable v2.

Voici l'exemple de l'utilisation:

La directive et le contrôleur sont:

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

Et le html (notez la différence pour @ et =):

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

Voici une lien sur le blog qui le décrit bien.


33
2018-04-26 16:34



Simplement nous pouvons utiliser: -

  1. @ : - pour les valeurs de chaîne pour une liaison de données à sens unique. dans un sens liaison de données, vous pouvez seulement transmettre la valeur de la portée à la directive

  2. = : - pour la valeur d'objet pour la liaison de données bidirectionnelle. Dans la liaison de données bidirectionnelle, vous pouvez modifier la valeur de la portée dans la directive ainsi que dans html également.

  3. & : - pour les méthodes et les fonctions.

MODIFIER

Dans notre Composant définition pour Version angulaire 1.5 Et ci-dessus
il existe quatre types de fixations:

  1. =  Liaison de données bidirectionnelle : - si nous changeons la valeur, il met à jour automatiquement
  2. <  liaison à sens unique : - quand on veut juste lire un paramètre d'une portée parent et ne pas le mettre à jour.

  3. @ c'est pour Paramètres de chaîne

  4. & c'est pour Rappels dans le cas où votre composant a besoin de produire quelque chose à sa portée parente


21
2017-08-29 10:44



J'ai créé un petit fichier HTML qui contient du code angulaire démontrant les différences entre eux:

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



le = manière Liaison bidirectionnelle, ce qui vous permet d'avoir vivre changements à l'intérieur de votre directive. Quand quelqu'un change cette variable hors de la directive, vous aurez cette donnée modifiée dans votre directive, mais @ manière n'est pas liaison à double sens. Cela fonctionne comme Texte. Vous liez une fois, et vous n'aurez que sa valeur.

Pour l'obtenir plus clairement, vous pouvez utiliser cet excellent article:

Champ d'application de la directive AngularJS '@' et '='


7
2018-05-10 23:03



@ La propriété scope locale est utilisée pour accéder aux valeurs de chaîne définies en dehors de la directive.

= Dans les cas où vous devez créer une liaison bidirectionnelle entre la portée externe et la portée isolate de la directive, vous pouvez utiliser le caractère =.

& La propriété locale scope permet au consommateur d'une directive de transmettre une fonction que la directive peut invoquer.

Veuillez vérifier le lien ci-dessous qui vous donne une compréhension claire avec des exemples. Je l'ai trouvé vraiment très utile alors pensé à le partager.

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


4
2018-02-05 13:12