265 votes

Lorsque vous écrivez une directive, comment décider si un besoin aucune nouvelle étendue, une nouvelle portée de l’enfant ou une nouvelle isoler portée ?

Je suis à la recherche de quelques lignes directrices que l'on peut utiliser pour aider à déterminer quel type de champ à utiliser lors de l'écriture d'une nouvelle directive. Idéalement, j'aimerais quelque chose de semblable à un diagramme de flux qui marche moi un tas de questions et sort la réponse correcte – pas de nouveaux de nouveaux de la portée, de la nouvelle enfant, ou de nouvelles isoler portée – mais c'est probablement trop demander. Voici ma maigre ensemble de lignes directrices:

  • n'utilisez pas d'isoler la portée si l'élément qui va utiliser la directive ng-model
    Voir ngModel et composant isolé avec de la portée et de la
    Pourquoi les formateurs ne fonctionne pas avec isolé portée?
  • si la directive ne modifie pas la portée et les propriétés de modèle, de ne pas créer un nouveau champ d'application
  • isoler les étendues semblent bien fonctionner si la directive contient un ensemble d'éléments du DOM (les docs disent "un complexe DOM structure") et la directive sera utilisé comme un élément, ou n'ayant pas d'autres directives sur le même élément

Je suis conscient que l'utilisation d'une directive avec un isolat portée sur un élément des forces de toutes les autres directives sur le même élément à utiliser la même (un) isoler l'étendue, n'est-ce pas limiter sévèrement quand un isolat champ d'application peut être utilisé?

J'espère que certains de l'Angulaire de l'INTERFACE utilisateur de l'équipe (ou d'autres qui ont écrit de nombreuses directives) peuvent partager leurs expériences.

Merci de ne pas ajouter une réponse qui dit simplement "utiliser un isolat portée de composants réutilisables".

289voto

Josh David Miller Points 66508

Quelle bonne question! J'avais de l'amour pour entendre ce que les autres ont à dire, mais ici sont les lignes directrices que j'utilise.

La haute altitude de ce principe: la portée est utilisé comme la "colle" que nous utilisons pour communiquer entre le contrôleur de parent, de la directive et de la directive modèle.

Parent: scope: false, donc pas de nouveau champ d'application à tous les

Je ne l'utilise pas très souvent, mais comme @MarkRajcok dit, si la directive n'a pas accès à toute la portée des variables (et évidemment ne définit pas tout!) alors c'est tout simplement parfait pour autant que je suis concerné. C'est également utile pour les enfants des directives qui sont uniquement utilisées dans le contexte de la société mère de la directive (mais il y a toujours des exceptions) et qui n'ont pas de modèle. Fondamentalement, quelque chose avec un modèle qui n'appartient pas, le partage d'un champ, parce que vous êtes intrinsèquement exposant que l'étendue de l'accès et de manipulation (mais je suis sûr qu'il y a des exceptions à cette règle).

Comme un exemple, j'ai créé récemment une directive qui dessine un (statique) des graphiques vectoriels à l'aide d'une SVG de la bibliothèque, je suis dans le processus de l'écriture. C' $observes deux attributs (width et height) et les utilise dans ses calculs, mais il ne fixe ni ni lit toute la portée des variables et n'a pas de modèle. C'est un bon cas d'utilisation à ne pas en créer un autre champ; nous n'en avons pas besoin, alors pourquoi s'embêter?

Mais dans un autre SVG directive, cependant, j'ai tenu un ensemble de données à utiliser et en outre eu pour stocker un tout petit peu de l'état. Dans ce cas, à l'aide de la portée parent serait irresponsable (encore une fois, d'une manière générale). Ainsi, au lieu...

Enfant: scope: true

Directives avec un enfant de la portée du compte du contexte et sont destinés à interagir avec le champ d'application actuel.

Évidemment, un avantage clé de ce sur un isolat portée est que l'utilisateur est libre d'utiliser l'interpolation sur les attributs qu'ils veulent, par exemple, à l'aide de class="item-type-{{item.type}}" sur une directive avec un isolat champ d'application ne fonctionnera pas par défaut, mais fonctionne très bien sur l'autre avec un enfant car tout ce qui est interpolée peut toujours, par défaut, être trouvé dans la portée parent. Aussi, la directive elle-même peut évaluer en toute sécurité des attributs et des expressions dans le contexte de son propre champ d'application sans se soucier de la pollution ou des dommages à la société mère.

Par exemple, une info-bulle est quelque chose qui est ajouté; un isolat champ d'application ne fonctionne pas (par défaut, voir ci-dessous) car il est prévu que nous allons utiliser d'autres directives ou interpolées attributs ici. L'info-bulle est juste une amélioration. Mais l'info-bulle a également besoin de mettre certaines choses sur le champ d'application à utiliser avec un sous-directive et/ou d'un modèle et, évidemment, de gérer son propre état, de sorte qu'il serait tout à fait mauvaise, en effet, l'utilisation de la portée parent. Nous sommes soit le polluant ou de l'endommager, et ni est bueno.

Je trouve moi-même à l'aide de l'enfant étendues plus souvent que de l'isoler ou étendues parents.

Isoler portée: scope: {}

C'est pour composants réutilisables. :-)

Mais sérieusement, je pense que des "composants réutilisables" comme "composantes autonomes". Le but est qu'ils sont à être utilisé dans un but précis, afin de les combiner avec d'autres directives ou d'ajouter d'autres interpolées attributs du nœud DOM, intrinsèquement, ne fait pas de sens.

Pour être plus précis, rien besoin de cette fonctionnalité autonome est fourni par les attributs évalués dans le contexte de la portée parent; ils sont un moyen de cordes ('@'), les expressions ('&'), ou une variable de liaisons ('=').

Sur des composantes autonomes, il n'a pas de sens à la nécessité d'appliquer d'autres directives ou des attributs sur elle parce qu'elle existe par elle-même. Son style est régi par son propre modèle (si nécessaire) et peut avoir le contenu approprié transcluded (si nécessaire). Il est autonome, donc nous l'avons mis dans un isolat portée aussi de dire: "Ne plaisante pas avec cela. Je vais vous donner un définies API à travers ces quelques attributs."

Une bonne pratique consiste à exclure autant basés sur le modèle des trucs de la directive lien et les fonctions du contrôleur que possible. Cela fournit un autre "API" comme de la configuration de point: l'utilisateur de la directive suffit de remplacer le modèle! La fonctionnalité reste la même, et son API interne n'a jamais été touché, mais on peut mess avec le style et DOM la mise en œuvre autant que nous en avons besoin. ui/bootstrap est un excellent exemple de la façon de le faire parce que Peter & Pawel sont impressionnantes.

Isoler les étendues sont également idéal pour une utilisation avec transclusion. Prendre des onglets; ils ne sont pas seulement l'ensemble des fonctionnalités, mais tout ce qui est à l'intérieur de celui-ci peut être évaluée librement à partir de l'intérieur de la portée parent tout en laissant les pattes (et volets) à faire ce qu'ils veulent. Les onglets ont clairement leur propre état, qui appartient au champ d'application (pour interagir avec le modèle), mais que l'état n'a rien à voir avec le contexte dans lequel il a été utilisé - il est entièrement interne à ce qui fait un onglet directive sur l'onglet de la directive. De plus, il n'a pas beaucoup de sens d'utiliser toutes les autres directives avec les onglets. Ils sont les onglets - et nous avons déjà obtenu que la fonctionnalité!

L'entourer avec plus de fonctionnalités, ou transclude plus de fonctionnalités, mais la directive est ce qu'il est déjà.

Tout ce que dit, je remarque qu'il y a des façons de contourner certaines limitations (c'est à dire les caractéristiques) d'un isolat de portée, comme @ProLoser fait allusion dans sa réponse. Par exemple, l'enfant du champ de l'article, j'ai mentionné l'interpolation sur la non-directive sur les attributs de la rupture lors de l'utilisation d'un isolat champ d'application (par défaut). Mais l'utilisateur pourrait, par exemple, il suffit d'utiliser class="item-type-{{$parent.item.type}}" et il aurait une fois de plus le travail. Donc, si il ya une raison impérieuse d'utiliser un isolat de la portée d'un enfant de la portée, mais vous êtes inquiet au sujet de certaines de ces limitations, sachez que vous pouvez travailler autour de pratiquement tous d'entre eux si vous en avez besoin.

Résumé

Les Directives aucun nouveau champ d'application sont en lecture seule; ils sont entièrement digne de confiance (c'est à dire interne à l'application) et qui ne touchent pas à jack. Les Directives de l'enfant portée ajouter des fonctionnalités, mais ils ne sont pas la seule fonctionnalité. Enfin, isoler les étendues de directives, l'ensemble de l'objectif; ils sont autonomes, de sorte qu'il est normal (et la plus "correcte"), pour se laisser aller voyous.

Je voulais faire mes premières réflexions, mais comme je le pense de plus en plus de choses, je vais mettre à jour ce. Mais holy crap - c'est long une SORTE de réponse...


PS: Totalement dans le sens tangentiel, mais puisque nous parlons étendues, je préfère dire "prototypique", tandis que d'autres préfèrent "prototypes", qui semble être plus précis, mais juste le sort de la langue pour ne pas bien du tout. :-)

52voto

ProLoser Points 2927

Ma politique du personnel et de l'expérience:

Isolé: un privé sandbox

Je veux créer beaucoup de portée des méthodes et des variables qui ne sont utilisés que par mon directive et ne sont jamais vu ou directement accessible par l'utilisateur. Je veux la liste blanche de ce champ de données est disponible pour moi. Je peux utiliser transclusion pour permettre à l'utilisateur de revenir à la portée parent (non affectée). Je n'ai PAS envie que mon variables et méthodes accessibles dans transcluded enfants.

Enfant: un paragraphe de contenu

Je veux créer une étendue de méthodes et de variables qui PEUVENT être accédés par l'utilisateur, mais ne sont pas pertinents à l'environnement étendues (frères, sœurs et parents) en dehors du contexte de mon directive. Je tiens également à laisser TOUS les parents de la portée des données à descendre de façon transparente.

Aucun: simple, en lecture seule directives

Je n'ai pas vraiment besoin de jouer avec la portée des méthodes ou variables. Je vais sans doute faire quelque chose qui n'a pas à faire avec des étendues (comme l'affichage simple jQuery plugins, validation, etc).

Notes

  • Vous ne devriez pas laisser ngModel ou d'autres choses directement un impact sur votre décision. Vous pouvez contourner le comportement étrange en faisant des choses comme ng-model=$parent.myVal (enfant) ou ngModel: '=' (isoler).
  • Isoler + transclude permettra de restaurer tous les comportement normal de la fratrie des directives et des retours à la portée parent, alors ne vous laissez pas influencer votre jugement.
  • Ne salissez pas avec le champ d'application sur aucun parce que c'est comme mettre des données sur le champ d'application de la moitié inférieure de la DOM, mais pas la moitié supérieure qui rend 0 sens.
  • Attention à la directive priorités (ne pas avoir des exemples concrets de la façon dont cela peut affecter les choses)
  • Injecter des services ou de l'utilisation des contrôleurs pour communiquer à travers les directives avec n'importe quel type de portée. Vous pouvez aussi le faire require: '^ngModel' à la regarder dans les éléments parents.

18voto

Umur Kontacı Points 12524

Après avoir écrit beaucoup de directives, j'ai décidé d'utiliser moins d' isolated de la portée. Même si il est cool et vous encapsuler les données et être sûr de ne pas la fuite de données à la portée parent, il limite fortement la quantité de directives que vous pouvez utiliser. Donc,

Si la directive que vous allez écrire va se comporter entièrement sur son propre et vous n'allez pas à la partager avec d'autres directives, allez isolé portée. (comme un composant vous pouvez il suffit de le brancher, avec pas beaucoup de personnalisation pour la fin développeur) (il devient très délicat lorsque vous essayez d'écrire des sous-éléments qui ont directives à l'intérieur)

Si la directive que vous allez écrire va juste faire les manipulations dom qui a besoin d'aucun état interne de la portée, ou explicite la portée des modifications (pour la plupart des choses très simples); allez pour aucun nouveau champ d'application. (comme ngShow, ngMouseHover, ngClick, ngRepeat)

Si la directive que vous allez écrire doit changer certains éléments de parent champ d'application, mais a aussi besoin de gérer un état interne, aller pour le nouvel enfant de la portée. (comme ngController)

Soyez sûr de vérifier le code source de directives: https://github.com/angular/angular.js/tree/master/src/ng/directive
Il contribue grandement sur la façon de penser à eux

9voto

user2483724 Points 392

Juste pensé que je voudrais ajouter ma compréhension actuelle et comment il se rapporte à d'autres JS concepts.

Par défaut (par exemple, non déclarée ou étendue: false)

C'est philosophiquement équivalent à l'utilisation de variables globales. Votre directive peut accéder à tout dans le contrôleur de parent, mais il est également affecter et d'être affecté en même temps.

champ d'application:{}

C'est comme un module, tout ce qu'il veut à utiliser doit être transmis explicitement. Si TOUTES les directives que vous utilisez est un isolat de portée, il peut être l'équivalent de faire de CHAQUE fichier JS vous écrire son propre module avec une surcharge importante de l'injection toutes les dépendances.

champ d'application: enfant

C'est le juste milieu entre des variables globales et explicite passthrough. Il est semblable à du javascript prototype de la chaîne et juste s'étend une copie de la portée parent. Si vous créez un isolat de la portée et de passer dans chaque attribut et la fonction de la portée parent ce est fonctionnellement équivalent à cela.


La clé est que TOUTE directive peut être écrit QUELQUE sorte. La portée des déclarations sont juste là pour vous aider à vous organiser. Vous pouvez faire tout ce qu'un module, ou vous pouvez simplement utiliser toutes les variables globales et être très prudent. Pour la facilité d'entretien mais il est préférable de modularalize votre logique dans logiquement cohérent de pièces.Il y a un équilibre entre un pré ouvert et un fermé de la prison de la maison. La raison que c'est difficile, je crois, c'est que quand les gens apprennent à propos de ce qu'ils pensent qu'ils sont l'apprentissage sur la façon de directives de travail, mais en réalité, ils font l'apprentissage du code, de la logique de l'organisation.

Une autre chose qui m'a aidé à comprendre la manière dont les directives de travail est d'apprendre à propos de ngInclude. ngInclude vous aidera à inclure html partiels. Quand j'ai commencé à l'aide de directives j'ai trouvé que l'on pouvait utiliser l'option modèle de réduire votre code, mais je n'étais pas vraiment attachant toute logique.

Bien sûr, entre angulaire de directives et le travail de l' angulaire de l'interface utilisateur de l'équipe, je n'ai pas encore eu à créer mon propre directive qui n'a rien de substantiel, pour mon point de vue sur ce qui peut être tout à fait tort.

2voto

RaceRadar Points 1

Je suis d'accord avec Umur. En théorie, isolé étendues sonores merveilleux et "portable", mais dans la construction de mon application à impliquer non négligeable de fonctionnalités, je suis tombé sur la nécessité d'intégrer plusieurs directives (certains imbriquée à l'intérieur d'autres ou en ajoutant des attributs) afin de bien l'écrire dans mon propre code HTML, ce qui est le but d'un Langage Spécifique au Domaine.

En fin de compte, il est trop bizarre d'avoir à passer chaque globale ou de la valeur partagée de la chaîne avec plusieurs attributs sur chaque DOM invocation d'une directive (comme il est requis à isoler le champ d'application). Il a juste l'air stupide à plusieurs reprises d'écrire tout ce que dans les DOM et il se sent inefficace, même si ce sont des objets partagés. Il a également complique inutilement la directive déclarations. La solution de contournement de l'utilisation de $parent à "atteindre" et de saisir les valeurs de la directive HTML semble Très Mauvaise Forme.

Moi aussi, j'ai liquidé mon changement d'application pour la plupart des enfants de la portée des directives très peu d'isolats -- seuls ceux qui n'ont pas besoin d'accéder à quelque CHOSE de la mère autre que ce qu'ils peuvent être passés à travers simple, non répétitives attributs.

Après avoir rêvé le rêve de Domaine Spécifique de Langues pendant des décennies, avant il y avait une telle chose, je suis ravie que AngularJS propose cette option et je sais que, comme de plus en plus les devs travaillent dans ce domaine, nous allons voir quelques très cool apps qui sont aussi facile pour leurs architectes d'écrire, de développer, et de débogage.

- D

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X