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/
=
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.Réponses:
@ lie une propriété de portée locale / directive à la valeur évaluée de l'attribut DOM . Si vous utilisez
title=title1
outitle="title1"
, la valeur de l'attribut DOM "title" est simplement la chaînetitle1
. Si vous utiliseztitle="{{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.
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.
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
la source
@
('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.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.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:
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 rappelLes 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éthodePar ordre d'utilité (pour moi en tout cas):
la source
"&"
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éponsecallback(argument)
. Ce qui n'est toujours pas le même quecallback
lui.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-title
recevra 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).
la source
Si vous souhaitez voir comment cela fonctionne avec un exemple en direct. http://jsfiddle.net/juanmendez/k6chmnch/
la source
@
obtenir comme chaîne=
Reliure 2 voies&
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.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&
la source
La directive peut être ajoutée de trois manières:
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.
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,
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,
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:
@ 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:
Et le html (notez la différence pour @ et =):
Voici un lien vers le blog qui le décrit bien.
la source
Nous pouvons simplement utiliser: -
@ : - 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
= : - 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.
& : - 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:
=
Liaison de données bidirectionnelle : - si nous modifions la valeur, elle se met automatiquement à jour<
liaison à sens unique : - lorsque nous voulons simplement lire un paramètre à partir d'une portée parent et ne pas le mettre à jour.@
c'est pour les paramètres de chaîne&
c'est pour les rappels au cas où votre composant aurait besoin de sortir quelque chose dans sa portée parentla source
J'ai créé un petit fichier HTML qui contient du code angulaire démontrant les différences entre eux:
la source
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 '='
la source
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:Ici, la
description
propriété dans la portée enfant sera la valeur actuelle de l'expression"The movie title is {{$ctrl.movie.title}}"
, oùmovie
est 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 ):Étant donné
parentVar=10
, l'expressionparentFoo({myVar:5, myOtherVar:'xyz'})
sera évaluée5 + 10 + 'xyz'
et le composant sera rendu comme suit: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
&
:Rappel en utilisant
<
: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 :Cela propagera la valeur de
tagline
la portée enfant sans établir de liaison unidirectionnelle ou bidirectionnelle. Remarque : sitagline
est initialementundefined
dans 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.
la source
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
la source
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, quititle
est défini sur la portée parent. Vous pouvez ensuite accéder au titre en tant que$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.
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
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$digest
cycle, ce qui n'est pas bon, car l'enregistrement est alors immédiatement supprimé et jamais rendu.la source
J'ai implémenté toutes les options possibles dans un violon.
Il traite de toutes les options:
https://jsfiddle.net/rishulmatta/v7xf2ujm
la source
la principale différence entre eux est juste
la source
@
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
expr
sera 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
x
et le paramètre parenty
.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 casx
.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>
appels5 == $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
la source
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.
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.
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
la source
@ Liaison de chaîne d'attribut (unidirectionnelle) = Liaison de modèle bidirectionnelle et liaison de méthode de rappel
la source
@ 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
la source