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


1067

J'ai lu attentivement la documentation AngularJS sur le sujet, puis j'ai tripoté une directive. Voici le violon .

Et voici quelques extraits pertinents:

  • Du HTML :

    <pane bi-title="title" title="{{title}}">{{text}}</pane>
  • Depuis 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 indique "Souvent, il est souhaitable de transmettre des données de la portée isolée via l'expression et à la portée parent" , mais cela semble fonctionner correctement avec la liaison bidirectionnelle également. 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/


18
Bon point. La capacité de rechercher et de trouver des réponses est importante.
Jonathan


1
En termes simples, =est utilisé dans la directive isoler la portée pour activer la liaison bidirectionnelle et @ne met pas à jour le modèle, met uniquement à jour les valeurs de la portée de la directive.
STEEL

@iwein pourquoi votre code de violon sur jsfiddle.net/maxisam/QrCXh ne fonctionne pas avec googleapi - ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js ? Votre code ne fonctionne que si j'utilise votre cdn - code.angularjs.org/1.0.1/angular-1.0.1.js
MukulSharma

Je vois beaucoup de bonnes réponses ci-dessous, mais quelqu'un peut-il donner un pointeur sur la documentation angulaire officielle qui répond à cette question?
John Henckel

Réponses:


1151

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

@ lie une propriété de portée locale / directive à la valeur évaluée de l'attribut DOM . Si vous utilisez title=title1ou title="title1", la valeur de l'attribut DOM "title" est simplement la chaîne title1. Si vous utilisez 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. Étant donné que les valeurs d'attribut sont toujours des chaînes, vous vous retrouverez toujours avec une valeur de chaîne pour cette propriété dans la portée de la directive lorsque vous utilisez @ .

= lie une propriété de portée locale / directive à une propriété de portée parent . Ainsi, avec = , vous utilisez le nom de la propriété du modèle / étendue parent 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 correspond à ce que la propriété de portée 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 de lien (ing). Par exemple, if(scope.title == "...")ne fonctionnera pas comme prévu. Notez que cela signifie que vous ne pouvez accéder à cet attribut que de manière 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 uniquement si vous n'utilisez pas de portée isolée. Supprimez cette ligne de votre directive

scope: { ... }

puis 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 d'étendue parent.

La documentation indique "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 également. 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 simplement appeler une fonction définie dans la portée parent - vous pouvez utiliser la syntaxe & .

Voir également


1
Huh, c'est un comportement vraiment bizarre, surtout quand on n'utilise pas d'interpolation et qu'on essaie juste de passer une chaîne. Apparemment, la demande de tirage a en effet été fusionnée dans les versions de développement et se trouve dans les versions RC 1.1.5 et 1.2.0. Bon pour eux d'avoir corrigé ce comportement très peu intuitif!
Ibrahim

50
Écrire '@' ou '=' est tellement plus clair qu'écrire "eval-dom" ou "parent-scope" ou tout autre texte lisible par l'homme. Bonne décision de conception.
Den

13
@('at') copie la valeur de 'ATtribute'. =(«égal») équivaut à dire que la clé est égale à votre expression. C'est du moins ainsi que je les retiens.
Matt DeKrey

1
Êtes-vous sûr que = ne concerne que les propriétés de portée parent? Toute expression semble fonctionner - pas seulement les propriétés de portée parent.
Jonathan Aquino

4
@JonathanAquino, oui cela fonctionne, mais @ serait plus approprié - avec foo="{{1+1}}"- car nous n'avons pas besoin de la liaison de données bidirectionnelle ici. Le point que j'ai essayé de faire valoir dans le commentaire ci-dessus est que nous ne devons utiliser = que lorsque la directive a besoin d'une liaison de données bidirectionnelle. Utilisez @ ou & autrement.
Mark Rajcok

542

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

Les trois liaisons sont des moyens de transmettre des données de votre portée parent à la portée isolée de votre directive via les attributs de l'élément:

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

  2. = la liaison est pour la liaison de modèle bidirectionnelle. Le modèle dans la portée parent est lié au modèle dans la portée isolée de la directive. Les modifications apportées à un modèle affectent l'autre et vice versa.

  3. & binding est pour passer une méthode dans le champ d'application de votre directive afin qu'elle puisse être appelée 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 hello (name) dans la portée parent, alors pour exécuter la méthode depuis l'intérieur de votre directive, vous devez appeler $ 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 bidirectionnelle
  • & Liaison de méthode de rappel

Les symboles indiquent également plus clairement ce que la variable scope représente à l'intérieur de l'implémentation de votre directive:

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

Par ordre d'utilité (pour moi en tout cas):

  1. =
  2. @
  3. &

13
En fait, "&"prend en charge les arguments (ou plutôt les sections locales) de la forme:, callback({foo: "some value"})qui pourraient ensuite être utilisés <my-dir callback="doSomething(foo)">. Sinon, bonne réponse
New Dev

11
Devrait être accepté la réponse. Voici un article concis avec les mêmes informations, mais avec des exemples de code ajoutés: umur.io/…
Kevin

4
& N'EST PAS une "liaison de méthode de rappel", c'est une liaison d'expression angulaire. Un exemple particulier mais pas le seul est l'expression callback(argument). Ce qui n'est toujours pas le même que callbacklui.
Dmitri Zaitsev

14
Bien que j'aie aimé à quel point la réponse de rang supérieur était définitive, j'ai trouvé que celle-ci avait un impact plus utile et après avoir lu celle-ci, j'ai beaucoup mieux compris la réponse précédente.
rbnzdave

1
Je suis d'accord avec le commentaire ci-dessus, cette réponse est plus claire, définitive et utile à la question. Il explique avec suffisamment de détails que vous pouvez aller utiliser les informations.
user3125823

64

La =liaison bidirectionnelle signifie, 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, cela <pane bi-title="{{title}}" title="{{title}}">{{text}}</pane>devrait aussi fonctionner. bi-titlerecevra la valeur de la variable de portée parent, qui peut être modifiée dans la directive.

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


1
Oui, cette partie que je reçois, voyez le violon dans la question. Mais qu'en est-il des parties qui ne sont pas claires?
iwein

4
le fait est que {{}} ne fonctionne pas avec =. = n'est pas évalué, mais la chaîne est considérée comme le nom de la propriété. Merci d'avoir répondu!
iwein

1
Je ne pense pas que = soit juste pour les variables dans la portée parent. Cela fonctionne avec n'importe quelle expression (par exemple, 1 + 1).
Jonathan Aquino

1
@JonathanAquino vous avez raison qu'il évalue les expressions. à mon humble avis, c'est en fait bizarre et je ne l'utiliserais pas de cette façon. C'est ce genre de trucs astucieux qui rendent les champs d'application des directives si difficiles à comprendre pour moi en premier lieu.
iwein

1
Suis-je le seul à penser que cette réponse est fausse! '=' signifie angulaire attend une expression javascript et fera un mappage bidirectionnel si une variable de portée est passée. Alors que @ mean angular attend une String et tout ça. En fait, il est vrai que si vous utilisez @ en combinaison avec {{}}, vous clonerez la valeur de la variable. Mais ce n'est pas la définition de @!
Luc DUZAN

39

Si vous souhaitez voir 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>"
    };
});

2
Il y a plusieurs exemples liés dans la question et la réponse supérieure. Qu'est-ce que cela ajoute?
iwein

10
@iwein, cela ajoute de la clarté. Si je pouvais comprendre et assimiler des exemples complets, je n'aurais pas besoin de ce site.
Tony Ennis

3
juan, peut-être réparer tes fautes de frappe? «transclude» est mal orthographié. mieux encore, supprimez-le (et tout le reste, comme «remplacer») qui ne contribue pas directement au problème afin que votre solution soit encore plus simple et plus claire. +1 pour l'exemple.
Tony Ennis

merci @AnikISlamAbhi pour l'édition. J'aimerais contribuer davantage et je suis heureux que certains trouvent mes échantillons utiles. C'est le but principal.
Juan Mendez

Exemple incomplet. Dans votre démonstration, vous modifiez uniquement la valeur bidirectionnelle. Vous n'essayez même pas de modifier une valeur dont la portée est isolée. Ainsi, il ne montre pas correctement comment fonctionne le champ d'application dans les directives.
Sudarshan_SMD

38

@ obtenir comme chaîne

  • Cela ne crée aucune liaison. Vous obtenez simplement le mot que vous avez transmis sous forme de 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 retourne l'objet qui a été transmis . Je suppose que c'était nécessaire pour le faire fonctionner. Le violon devrait clarifier cela.

  • Après avoir appelé cette fonction getter, l'objet résultant se comporte comme suit:
    • si une fonction a été passée: alors la fonction est exécutée dans la fermeture parent (contrôleur) lorsqu'elle est appelée
    • si une non-fonction a été transmise: obtenez simplement une copie locale de l'objet qui n'a pas de liaisons


Ce violon devrait montrer comment ils fonctionnent . Portez une attention particulière aux fonctions de portée avec get...le nom pour, espérons-le, mieux comprendre ce que je veux dire&


36

La directive peut être ajoutée de trois manières:

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

La directive et son champ d'application parent (contrôleur / directive dans lequel elle se trouve) sont identiques. Ainsi, toutes les modifications apportées aux variables de portée dans la directive sont également reflété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 : la directive crée une portée enfant qui hérite de la portée parent si vous spécifiez la variable de portée de la directive comme vraie.

Ici, si vous modifiez les variables de portée dans la directive, cela ne se reflétera pas dans la portée parent, mais si vous modifiez la propriété d'une variable de portée, cela se reflète dans la portée parent, car vous avez réellement 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 : cette option est utilisée lorsque vous souhaitez 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 code HTML et n'est pas affectée par sa portée parent.

Maintenant, si vous ne voulez aucune 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

Généralement, ce n'est pas le cas car nous avons besoin d'une certaine interaction avec la portée parent, 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 modifications de la portée du contrôleur seront reflétées 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 encapsuler la valeur d'attribut dans {{}}.

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

& 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 d'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 un lien vers le blog qui le décrit bien.


& n'est ni "liaison de comportement" ni "liaison de méthode", c'est une liaison d'expression angulaire.
Dmitri Zaitsev

20

Nous pouvons simplement utiliser: -

  1. @ : - pour les valeurs de chaîne pour la liaison de données à sens unique. d'une manière la liaison de données, vous ne pouvez transmettre la valeur de portée à la directive

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

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

ÉDITER

Dans notre définition de composant pour Angular version 1.5 et ci-dessus,
il existe quatre types différents de liaisons:

  1. = Liaison de données bidirectionnelle : - si nous modifions la valeur, elle se met automatiquement à jour
  2. < liaison à sens unique : - lorsque nous voulons simplement lire un paramètre à partir d'une portée parent et ne pas le mettre à jour.

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

  4. &c'est pour les rappels au cas où votre composant aurait besoin de sortir quelque chose dans sa portée parent


13

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>

6

La manière = est une liaison bidirectionnelle , qui vous permet d'avoir des changements en direct dans votre directive. Lorsque quelqu'un modifie cette variable hors de la directive, vous aurez ces données modifiées dans votre directive, mais @ way n'est pas une liaison bidirectionnelle . Cela fonctionne comme du 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 '='


6

Cette question a déjà été battue à mort, mais je la partagerai de toute façon au cas où quelqu'un d'autre serait aux prises avec le désordre horrible qu'est la portée d'AngularJS. Cette couverture de volonté =, <, @, &et ::. La rédaction complète peut être trouvée ici .


=établit une liaison bidirectionnelle. La modification de la propriété dans le parent entraînera un changement dans l'enfant, et vice versa.


<établit une liaison à sens unique, parent à enfant. La modification de la propriété dans le parent entraînera un changement dans l'enfant, mais la modification de la propriété enfant n'affectera pas la propriété parent.


@affectera à la propriété enfant la valeur de chaîne de l'attribut tag. Si l'attribut contient une expression , la propriété enfant est mise à jour chaque fois que l'expression est évaluée dans une chaîne différente. Par exemple:

<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
    description: '@', 
}

Ici, la descriptionpropriété dans la portée enfant sera la valeur actuelle de l'expression "The movie title is {{$ctrl.movie.title}}", où movieest un objet dans la portée parent.


&est un peu délicat, et en fait il ne semble pas y avoir de raison impérieuse de l'utiliser. Il vous permet d'évaluer une expression dans la portée parent, en remplaçant les paramètres par des variables de la portée enfant. Un exemple ( 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'
  }
});

Étant donné parentVar=10, l'expression parentFoo({myVar:5, myOtherVar:'xyz'})sera évaluée 5 + 10 + 'xyz'et le composant sera rendu comme suit:

<div>15xyz</div>

Quand voudriez-vous jamais utiliser cette fonctionnalité alambiquée? &est souvent utilisé par les utilisateurs pour passer à la portée enfant une fonction de rappel dans la portée parent. En réalité, cependant, le même effet peut être obtenu en utilisant «<» pour passer la fonction, qui est plus simple et évite la syntaxe des accolades maladroites maladroites pour passer les paramètres ( {myVar:5, myOtherVar:'xyz'}). Considérer:

Rappel en utilisant &:

<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: '&'
  }
});

Rappel en utilisant <:

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

Notez que les objets (et les tableaux) sont transmis par référence à la portée enfant, et non copiés. Cela signifie que même s'il s'agit d'une liaison unidirectionnelle, vous travaillez avec le même objet dans la portée parent et la portée enfant.


Pour voir les différents préfixes en action, ouvrez ce plunk .

Liaison unique (initialisation) à l'aide de ::

[Documents officiels]
Les versions ultérieures d'AngularJS introduisent l'option d'avoir une liaison unique, où la propriété de portée enfant n'est mise à jour qu'une seule fois. Cela améliore les performances en éliminant la nécessité de surveiller la propriété parent. La syntaxe est différente de celle ci-dessus; pour déclarer une liaison unique, vous ajoutez ::devant l'expression dans la balise du composant :

<child-component 
  tagline = "::$ctrl.tagline">
</child-component>

Cela propagera la valeur de taglinela portée enfant sans établir de liaison unidirectionnelle ou bidirectionnelle. Remarque : si taglineest initialement undefineddans la portée parent, angular le surveillera jusqu'à ce qu'il change, puis effectuera une mise à jour unique de la propriété correspondante dans la portée enfant.

Sommaire

Le tableau ci-dessous montre comment les préfixes fonctionnent selon que la propriété est un objet, un tableau, une chaîne, etc.

Fonctionnement des différentes liaisons de portée isolées


4

La propriété @ local scope 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 isolée de la directive, vous pouvez utiliser le caractère =.

La propriété & local scope permet au consommateur d'une directive de passer 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 j'ai pensé à le partager.

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


3

Même lorsque la portée est locale, comme dans votre exemple, vous pouvez accéder à la portée parent via la propriété $parent. Supposons dans le code ci-dessous, qui titleest défini sur la portée parent. Vous pouvez ensuite accéder au titre en tant que $parent.title:

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

Cependant, dans la plupart des cas, le même effet est mieux obtenu en utilisant des attributs.

Un exemple où j'ai trouvé la notation "&", qui est utilisée "pour passer des données de la portée isolée via une expression et à la portée parent", utile (et une liaison de données bidirectionnelle ne pouvait pas être utilisée) était dans une directive pour rendre une structure de données spéciale à l'intérieur d'une répétition ng.

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

Une partie du rendu était un bouton de suppression et ici, il était utile d'attacher une fonction de suppression de la portée extérieure via &. A l'intérieur de la directive de rendu, il ressemble

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

La liaison de données bidirectionnelle, c'est-à-dire data = "="ne peut pas être utilisée car la fonction de suppression s'exécuterait à chaque $digestcycle, ce qui n'est pas bon, car l'enregistrement est alors immédiatement supprimé et jamais rendu.



3

la principale différence entre eux est juste

@ Attribute string binding
= Two-way model binding
& Callback method binding

1

@et =voir d'autres réponses.

Un Gotcha sur les TL; DR; obtient l' expression (pas seulement la fonction comme dans les exemples dans d'autres réponses) d'un parent, et la définit comme une fonction dans la directive, qui appelle l'expression. Et cette fonction a la capacité de remplacer n'importe quelle variable (même le nom de la fonction) d'expression, en passant un objet avec les variables. &

&

expliqués
& est une référence d'expression, cela signifie que si vous passez quelque chose comme <myDirective expr="x==y"></myDirective>
dans la directive ce exprsera une fonction, qui appelle l'expression, comme:
function expr(){return x == y}.
donc dans le html de la directive <button ng-click="expr()"></button>appellera l'expression. Dans js de la directive $scope.expr()appellera simplement l'expression aussi.
L'expression sera appelée avec $ scope.x et $ scope.y du parent.
Vous avez la possibilité de remplacer les paramètres!
Si vous les définissez par appel, par exemple, <button ng-click="expr({x:5})"></button>
l'expression sera appelée avec votre paramètre xet le paramètre parent y.
Vous pouvez remplacer les deux.
Maintenant vous savez pourquoi ça <button ng-click="functionFromParent({x:5})"></button>marche.
Parce qu'il appelle simplement l'expression du parent (par exemple<myDirective functionFromParent="function1(x)"></myDirective>) et remplace les valeurs possibles par vos paramètres spécifiés, dans ce cas x.
il pourrait être:
<myDirective functionFromParent="function1(x) + 5"></myDirective>
ou
<myDirective functionFromParent="function1(x) + z"></myDirective>
avec appel enfant:
<button ng-click="functionFromParent({x:5, z: 4})"></button>.
ou même avec le remplacement de la fonction:
<button ng-click="functionFromParent({function1: myfn, x:5, z: 4})"></button>.

c'est juste une expression, peu importe si c'est une fonction, ou beaucoup de fonctions, ou juste une comparaison. Et vous pouvez remplacer n'importe quelle variable de cette expression.

Exemples:
modèle de directive vs code appelé: le
parent a défini $ scope.x, $ scope.y:
modèle parent: <myDirective expr="x==y"></myDirective>
<button ng-click="expr()"></button>appels $scope.x==$scope.y
<button ng-click="expr({x: 5})"></button>appels 5 == $scope.y
<button ng-click="expr({x:5, y:6})"></button>appels5 == 6

parent a défini $ scope.function1, $ scope.x, $ scope.y:
modèle parent:<myDirective expr="function1(x) + y"></myDirective>

<button ng-click="expr()"></button>appels $scope.function1($scope.x) + $scope.y
<button ng-click="expr({x: 5})"></button>appels $scope.function1(5) + $scope.y
<button ng-click="expr({x:5, y:6})"></button>appels $scope.function1(5) + 6
directive a $ scope.myFn comme fonction:
<button ng-click="expr({function1: myFn, x:5, y:6})"></button> appels$scope.myFn(5) + 6


0

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

Lorsque vous utilisez {{title}}, seule la valeur de portée parent sera transmise à la vue directive et évaluée. Ceci est limité à une seule façon, ce qui signifie que le changement ne sera pas reflété dans la portée parent. Vous pouvez utiliser '=' lorsque vous souhaitez également refléter les modifications apportées dans la directive enfant à la portée parent. C'est à double sens.

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

Lorsque la directive contient un attribut scope (scope: {}), vous ne pourrez plus accéder directement à la portée parent. Mais il est toujours possible d'y accéder via la portée. $ Parent etc. Si vous supprimez la portée de la directive, vous pouvez y accéder directement.

La documentation indique "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 également. Pourquoi la voie d'expression serait-elle meilleure?

Cela dépend du contexte. Si vous voulez appeler une expression ou une fonction avec des données, vous utilisez & et si vous voulez partager des données, vous pouvez utiliser la méthode bidirectionnelle en utilisant '='

Vous pouvez trouver les différences entre plusieurs façons de transmettre des données à la directive au lien ci-dessous:

AngularJS - Scopes isolés - @ vs = vs &

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


0

@ Liaison de chaîne d'attribut (unidirectionnelle) = Liaison de modèle bidirectionnelle et liaison de méthode de rappel


0

@ lie une propriété de portée locale / directive à la valeur évaluée de l'attribut DOM. = lie une propriété de portée locale / directive à une propriété de portée parent. & binding est pour passer une méthode dans le champ d'application de votre directive afin qu'elle puisse être appelée dans votre directive.

@ Attribute string binding = Liaison de modèle bidirectionnelle et liaison de méthode de rappel

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.