La directive est un moyen d'enseigner à HTML à jouer de nouvelles astuces. Pendant la compilation DOM, les directives correspondent à HTML et à l'exécution. Cela permet un comportement d'enregistrement directif ou de convertir les structures DOM.
Angular est livré avec un ensemble de directives intégrées, ce qui est très utile pour créer une application Web. Si vous continuez à vous développer, vous pouvez définir un langage spécifique au domaine (DSL) dans HTML.
1. CITATION DES DIRECTIVES EN HTML
La directive a une dénomination de style camel en tul, comme Ngbind (il semble être inutilisable dans les propriétés ~). Cependant, la directive peut également être nommée avec un type de fond de serpent (cas de serpent), qui doit être connecté via: (Colon), - (moins) ou _ (soulignement). En tant qu'option facultative, la directive peut être préfixée avec "x-" ou "data-" pour répondre aux besoins de vérification HTML. Voici les noms juridiques des directives:
La directive peut être placée dans les noms d'élément, les attributs, les classes et les commentaires. Ce qui suit est le moyen équivalent de citer MyDir, la directive. (Mais de nombreuses directives sont limitées à l'utilisation des "propriétés")
<span my-dir = "exp"> </span> <span> </span> <my-dir> </ my-diir> <! - Directive: my-dir exp ->
La directive peut être citée de diverses manières, et les éléments suivants répertorient n façons équivalentes:
<! Doctype html> <html lang = "zh-cn" ng -pp> <ead> <meta charset = "utf-8"> <itle> invoke-directive </tapt> <style type = "text / css"> .ng-coak {affiche: aucun; } </ style> </ head> <body> <div ng-controller = "myctrl"> Bonjour <entrée ng-model = "name" /> <hr /> ngbind = "name" Ceci ne peut pas être utilisé ~~ <span ngbind = "name"> </ span> <br/> ng: bind = "name" <span ng: bind = "name"> </ spande> ng_bind = "name" <span ng_bind = "name"> </span> <br/> ng-bind = "name" <span ng-bind = "name"> </span> <br/> data-ng-bind = "name" <span data-ng-bind = "name"> </ span> <br/> x-ng-bind = "name" <span " x-ng-bind = "name"> </span> <br/> </ div> <script src = "../ angular-1.0.1.js" type = "text / javascript"> </ script> <script type = "text / javascript"> function myctrl ($ scope) {$ scope.name = "Beauty ~~"; } </ script> </ body> </html>2. Interpolation de chaîne
Pendant le processus de compilation, le compilateur correspond au texte avec des expressions intégrées dans des attributs (tels que {{quelque chose}}) via le service $ interpolate. Ces expressions seront enregistrées en tant que montres et seront mises à jour dans le cadre du cycle Digest (ce n'était-ce pas une boucle de digest avant ?!). Voici une interpolation simple:
<img src = "img / {{nom d'utilisateur}}. jpg" /> Bonjour {{nom d'utilisateur}}!
3. Processus de compilation et correspondance directive
Trois étapes pour "compiler" HTML:
1. Tout d'abord, convertissez HTML en objets DOM via l'API standard du navigateur. C'est une étape très importante. Parce que le modèle doit être analysé (conforme aux spécifications). Cela peut être comparé à la plupart des systèmes de modèles, qui sont généralement basés sur des chaînes, pas des éléments DOM.
2. La compilation du DOM est effectuée en appelant la méthode $ comple (). Cette méthode traverse le DOM et correspond à la directive. Si le match réussit, il sera ajouté à la liste des directives avec le DOM correspondant. Tant que toutes les directives associées au DOM spécifié sont identifiées, elles seront triées en priorité et exécuteront leur fonction compile () dans cet ordre. Directive Compile Fonction a la possibilité de modifier la structure DOM et est responsable de la génération de l'analyse de la fonction Link (). La méthode $ compile () renvoie une fonction de liaison combinée, qui est une collection de fonctions liées renvoyées par la fonction de compilation de la directive elle-même.
3. Connectez le modèle à la portée via la fonction de liaison renvoyée à l'étape précédente. Cela appelle à son tour la fonction de liaison de la directive, leur permettant d'enregistrer certains auditeurs sur l'élément et de créer des montres avec Scope. Le résultat est une liaison instantanée bidirectionnelle entre la portée et le DOM. Lorsque la portée change, le DOM obtiendra la réponse correspondante.
var $ compile = ...; // injecté dans votre code var scope = ...; var html = '<div ng-bind =' exp '> </div>'; // Étape 1: Parse HTML dans Dom Element var template = angular.element (html); // Étape 2: compiler le modèle var linkfn = $ compile (modèle); // Étape 3: liez le modèle compilé avec la portée. linkfn (scope);
4. Raisons derrière la séparation de compilation / lien
Pour le moment, vous vous demandez peut-être pourquoi le processus de compilation est divisé en deux étapes: compiler et lien. Pour comprendre cela, jetons un coup d'œil à un vrai exemple (répéteur)
Bonjour {{user}}, vous avez ces actions: <ul> <li ng-repeat = "Action dans user.actions"> {{action.description}} </li> </ul>Autrement dit, la raison pour laquelle nous séparons les deux étapes de compilation et de liaison est que parfois la structure DOM correspondante doit être modifiée après la modification du modèle, comme les répéteurs.
Lorsque l'exemple ci-dessus est compilé, le compilateur itérera à travers tous les nœuds pour trouver la directive. {{user}} est un exemple d'une directive d'interpolation. Ngrepeat est une autre directive. Mais Ngrepeat a du mal. Cela nécessite la capacité de créer rapidement un nouveau Li pour chaque action dans les utilisateurs. Cela signifie que pour satisfaire le but de cloner Li et d'intégrer des actions spécifiques (se réfère ici à l'une des valeurs des actions de l'utilisateur), il doit conserver une copie propre de l'élément Li, qui doit être cloné et inséré dans l'élément UL. Mais le clonage de l'élément Li ne suffit pas. Li doit également être compilé afin que sa directive ({{Action.Descriptions}}) puisse être analysée dans la portée correcte. La méthode d'origine insère généralement simplement une copie de l'élément Li, puis la compile. Cependant, la compilation de copies de chaque élément Li sera plus lente, car le processus de compilation nous oblige à traverser l'arborescence du nœud Dom, à trouver des directives et à les exécuter. Si nous avons une compilation qui doit traiter 100 éléments via le répéteur, nous serons coincés avec des problèmes de performances.
La solution au problème consiste à décomposer le processus de compilation en deux étapes. L'étape de compilation reconnaît toutes les directives et les trie par priorité, liant une portée spécifique avec un LI spécifique pendant le stade de liaison.
Ngrepeat compile les LIS individuels séparément pour empêcher le processus de compilation de tomber dans les éléments Li. Le résultat de la compilation de l'élément Li est une fonction de liaison directive contenant toutes les directives contenues dans l'élément Li, prête à se connecter avec la copie de l'élément Li spécifique. Au moment de l'exécution, NGrepeat surveille l'expression et est ajouté en tant qu'élément à un tableau d'éléments Li Copies, créant une nouvelle portée pour les éléments Li clonés et appelant la fonction de liaison correspondant à la copie.
Résumer:
1. Fonction de compilation - Les fonctions de compilation sont relativement rares dans les directives, car la plupart des directives se soucient uniquement de travailler avec des éléments DOM spécifiés, plutôt que de modifier les modèles des éléments DOM (Dom lui-même et sa structure interne). Pour optimiser les performances, certaines opérations qui peuvent être partagées par des instances directives peuvent être déplacées dans la fonction de compilation.
2. Fonction de liaison - très peu de directives n'ont pas de fonction de lien. La fonction de liaison permet à la directive d'enregistrer un auditeur sur la copie spécifiée de l'instance DOM Élément, ou de copier du contenu spécifique de la portée dans le DOM.
5. Écrivez une directive (version simple)
Dans cet exemple, nous créerons une directive qui affiche l'heure actuelle en fonction du format d'entrée.
<! Doctype html> <html lang = "zh-cn" ng-app = "timeFormat"> <éadf> <méta charset = "utf-8"> <itle> Time-Format </ title> </ head> <body> <div ng-controller = "MyCtrl" id = "Main"> date Format: <puty ng-model = "Format" Type = "Text" /> <hr /> <! - L'attribut suivant-time à courant x est d'essayer la dénomination légale mentionnée ci-dessus ~~ Current: Time, Current-Time, Current_time, Data-Current-Time -_- !!! -> L'heure actuelle est: <span x-current-time = "format" id = "myformat"> </span> <br/> <Button ng-Click = "retire ()"> Supprimez le span </ Button> </div> <script src = "../ angulaire-1.0.1.js" type = "Text / javascript"> </script> <script type = "text / javascript"> angular.module ("TimeFormat", []) // Enregistrer la méthode de l'usine directive "CurrentTime" dans l'application TimeFormat // comme mentionné ci-dessus, l'injection de dépendance peut être écrite directement dans les paramètres de la fonction, injecté ici $ out et DataFilter .Directive ("Currenttime", fonction ajout) {// that is the lien furet. Fonction de compilation, pourquoi? ...) Return Fonction (Scope, élément, att) {var interalid; SCOPE. $ Watch (att.currentTime, fonction (valeur) {scope.Format = valeur; UpdateTime ();}); }). Controller ("myctrl", fonction ($ scope, $ rootscope) {$ scope.format = "m / d / yy h: mm: ss a"; $ scope.remove = function () {var oformat = document.getElementByid ("myformat"); if (oformat) {Angular.element (ofOrmat) .remove (); L'événement $ peut être déclenché!!6. Écrivez une directive (version détaillée)
Vous trouverez ci-dessous un exemple de création d'une directive (modèle de définition d'objet directif). Si vous souhaitez voir la liste détaillée, veuillez continuer à lire.
var mymodule = angular.module (...); Mymodule.Directive ('DiredivenName', fonction Factory (injectables) {var directiveFinIitionObject = {priority: 0, modèle: '<div> </div>', templateUrl: 'directive.html', remplacer: false, transclude: false, restrict: 'a', scope: false: function compil PreLlink (Scope, ielement, iantrs, contrôleur) {...}, post: fonction postLink (scope, ielement, iantrs, contrôleur) {...}}}, lien: fonction postLink (scope, ielement, iattrs) {...}};Dans la plupart des scénarios, nous n'avons pas besoin de contrôle précis, donc la définition ci-dessus peut être simplifiée. La définition de chaque partie du modèle sera expliquée dans le chapitre suivant. Dans ce chapitre, nous nous concentrons uniquement sur les isomères de ce squelette qui définissent le modèle (isomères de ce squelette, je ne comprends pas ... dans l'attente de l'ajout de tout le monde).
La première étape pour simplifier votre code consiste à s'appuyer sur des valeurs par défaut. Par conséquent, le code ci-dessus peut être simplifié à:
var mymodule = angular.module (...); MyModule.Directive ('DiredivenName', Function Factory (injectables) {var DireveVevedFinIitionObject = {compile: fonction compile (Tement, Tattrs) {return function postLink (scope, iElement, iattrs);La plupart des directives ne se soucient que des instances, pas de la conversion de modèle, donc elles peuvent être encore simplifiées (traduites très difficiles ... dans l'attente de l'ajout de tout le monde):
var mymodule = angular.module (...); myModule.Directive ('DiredivenName', fonction Factory (injectables) {return function postLink (scope, iElement, iantrrs) {...}});7. Méthode d'usine
La méthode d'usine est responsable de la création de directives. Il n'est utilisé qu'une seule fois, juste au moment où le compilateur correspond à la directive pour la première fois. Vous pouvez effectuer des opérations d'initialisation ici. La méthode d'usine est exécutée via $ inject
8. DESCRIPTION DE L'OBJET DE DÉFINITION DE LA directive
Les objets de définition directive fournissent la structure du compilateur. Les propriétés sont les suivantes:
1.Nom - Le nom de la portée actuelle. La valeur par défaut peut être utilisée lors de l'inscription (non remplie).
2. priorité - Lorsqu'il existe plusieurs directives définies dans le même élément DOM, il est parfois nécessaire de clarifier leur ordre d'exécution. Cette propriété est utilisée pour trier avant l'appel de fonction de compilation directive. Si la priorité est la même, l'ordre d'exécution est incertain (après les expériences préliminaires, les personnes ayant une priorité plus élevée sont exécutées en premier, et le même niveau est similaire à l'exécution "post-liaison" d'abord ". En outre, j'ai été un peu insouciant pendant le test.
3.Terminal (dernier groupe) - Si défini sur "Vrai", cela signifie que la priorité actuelle deviendra la directive du dernier groupe d'exécution. Si une directive est la même que la priorité actuelle, elle sera toujours exécutée, mais l'ordre est incertain (bien que l'ordre soit incertain, il est fondamentalement le même que l'ordre de priorité. Une fois la priorité actuelle exécutée, une priorité inférieure ne sera plus exécutée).
4.Scope - Si défini sur:
1) .True - Une nouvelle portée sera créée pour cette directive. S'il y a plusieurs directives dans le même élément qui nécessitent une nouvelle portée, cela ne créera toujours qu'une seule portée. Les nouvelles règles de portée ne s'appliquent pas au modèle racine, donc le modèle racine a tendance à obtenir une nouvelle portée.
2). {} (Objet Hash) - Une nouvelle étendue d'isolat sera créée. La différence entre la portée «isolée» et la portée générale est qu'elle n'est pas héritée de la portée des parents à travers des prototypes. Ceci est très utile pour créer des composants réutilisables et peut effectivement empêcher la lecture ou la modification des données de la portée des parents. Cette portée indépendante crée un hachage d'objet avec un ensemble de propriétés locales de portée dérivées de la portée des parents. Ces propriétés locales sont utiles pour aliaser les valeurs pour les modèles -_-!. La définition des locaux est un hachage de la propriété de portée locale à sa source # &) $ & @ #) ($ & @ # _):
3). @ Ou @Attr - Créez une propriété de portée locale sur la propriété DOM. Parce que la valeur de propriété est toujours du type de chaîne, cette valeur renvoie toujours une chaîne. Si le nom d'attribut n'est pas spécifié via @ATTR, le nom local sera toujours avec le nom de l'attribut DOM. Par exemple, <widget my-attr = ”Hello {{name}}">, la portée du widget est définie comme: {localName: '@ myattr'}. Ensuite, le nom local de la propriété de portée du widget mappera la valeur réelle convertie par "Hello {{name}}". Une fois la valeur de l'attribut de nom qui change, l'attribut localname de la portée du widget changera également en conséquence (seulement unidirectionnelle, différente du "=" ci-dessous). L'attribut de nom est lu dans la portée du parent (pas dans la portée du composant)
4). = OR = Expression (peut-être ART ici) - Définissez une liaison bidirectionnelle entre l'attribut de portée local et l'attribut de portée parent. Si le nom de l'attribue n'est pas spécifié, le nom local sera cohérent avec le nom d'attribut. Par exemple, <widget my-attr = ”parentModel”>, la portée définie par le widget est: {localModel: '= myAttr'}, alors la propriété de l'étendue du widget "LocalName" mappera "parentModel" de la portée du parent. Si des modifications se produisent dans ParentModel, LocalModel changera également, et vice versa. (Reliure bifaire)
5). & Ou & attir - fournit un moyen d'exécuter une expression dans le contexte de la portée des parents. Si le nom de l'attribue n'est pas spécifié, le nom local sera cohérent avec le nom d'attribut. Par exemple, <widget my-attr = ”count = count + value”>, la portée du widget est définie comme: {localfn: 'incrément ()'}, puis isoler la propriété de l'étendue "localfn" pointera vers une fonction enveloppée d'une expression incrément (). D'une manière générale, nous voulons transmettre des données de la portée de l'isolat à la portée des parents à travers une expression. Cela peut être fait en passant une carte de la valeur clé d'une variable locale dans la fonction de wrapper de l'expression. Par exemple, si l'expression est incrément (montant), nous pouvons appeler localfn via localFn ({montant: 22}) pour spécifier la valeur du montant (l'exemple ci-dessus ne comprend vraiment pas, et où êtes-vous allé?).
5.Contrôleur - Constructeur de contrôleur. Le contrôleur s'initialisera avant l'étape de préalable et permettra à d'autres directives de partager via le requis avec le nom spécifié (voir la propriété requise ci-dessous). Cela permettra aux directives de communiquer entre elles et d'améliorer le comportement mutuel. Le contrôleur injecte les objets locaux suivants par défaut:
1). $ Scope - Scope combinée avec l'élément actuel
2). $ Élément - élément actuel
3). $ Attrs - l'objet d'attribut de l'élément actuel
4). $ Transclude - une fonction de liaison de transposition pré-liée à la portée de transposition actuelle: fonction (ClonelingFn). (Une fonction de liaison transclude pré-liée à la portée de traduction correcte)
6.Require - Demandez à un autre contrôleur de le transmettre dans la fonction de liaison de la directive actuelle. Exigent que le nom d'un contrôleur direct soit transmis. Si le contrôleur correspondant à ce nom ne peut être trouvé, une erreur sera lancée. Le nom peut être préfixé avec les éléments suivants:
1).? - Ne lancez pas d'exceptions. Cela fait de cette dépendance une option.
2). ^ - un contrôleur qui permet de rechercher des éléments parents
7.restrict - une chaîne d'un sous-ensemble d'EACM, qui limite la directive à la méthode de déclaration spécifiée. S'il est omis, la directive n'autorisera les déclarations que via des attributs:
1) E - Nom de l'élément: <y-Directive> </y-Directive>
2) .A - Nom d'attribut: <div my-directive = ”exp"> </div>
3). C - Nom de la classe: <div class = "My-Directive: Exp;"> </div>
4) .m - Commentaire: <! - Directive: My-Directive Exp ->
8.Template - Si le remplacement est vrai, remplacez le contenu de modèle par l'élément HTML actuel et migrez ensemble les propriétés et la classe de l'élément d'origine; Si faux, l'élément de modèle est traité comme un élément enfant de l'élément actuel. Pour plus d'informations, veuillez consulter le chapitre "Création des widgets" (où ... la création de composants est disponible ...)
9.TemplateUrl - est fondamentalement le même que le modèle, mais le modèle est chargé via l'URL spécifié. Parce que le chargement du modèle est asynchrone, la compilation et la liaison seront interrompus et seront exécutés après le chargement.
10.replace - Si défini sur true, le modèle remplacera l'élément actuel au lieu d'être ajouté à l'élément actuel en tant qu'élément enfant. (Remarque: quand il est vrai, le modèle doit avoir un nœud racine)
11.Transclude - Compilez le contenu d'un élément afin qu'il puisse être utilisé par directive. Requis (dans le modèle) à utiliser (référencé). L'avantage de la transclusion est que la fonction de liaison peut obtenir une fonction de traduction pré-liée à la portée actuelle. Généralement, créez un widget et créez une portée d'isolat. La traduction n'est pas un enfant, mais un frère de la portée de l'isolat. Cela obligera le widget à avoir un état privé et la transclusion sera liée à la portée parent (pré-isolé). (Je ne comprends pas le paragraphe ci-dessus. Mais dans les expériences réelles, si MyDirective est appelée via <tout-directif> {{name}} </ tout-directif> et le transclude est défini sur true ou une chaîne et que le modèle contient <Stumegag ng-transclude>, le résultat de la compilation de {{nom}} sera inséré dans le contenu du contenu. sera une portée supplémentaire dans le sometag.
1) .True - Convertir le contenu de cette directive. (En ce sens, il s'agit de compiler directement le contenu et de le déplacer vers l'endroit désigné)
2). «Élément» - convertit l'élément entier, y compris d'autres directives avec une priorité inférieure. (Par exemple, après avoir compilé l'intégralité du contenu, il est traité dans son ensemble (P enveloppé à l'extérieur) et inséré dans l'endroit spécifié)
12.compile - Voici la fonction de compilation, qui sera expliquée en détail dans les chapitres suivants
13.Link - Voici la fonction de lien, qui sera expliquée en détail dans le chapitre suivant. Cette propriété n'est utilisée que si la propriété de compilation n'est pas définie.
9. Fonction de compilation
Fonction Compile (Tement, Tattrs, TransClude) {…}
La fonction de compilation est utilisée pour gérer la conversion des modèles DOM. Étant donné que la plupart des directives ne nécessitent pas de modèles de conversion, la compilation ne sera pas utilisée fréquemment. Directive qui nécessite une fonction de compilation, généralement celles qui ont besoin de convertir des modèles DOM (comme NGrepeat), ou ceux qui ont besoin de charger du contenu de manière asynchrone (comme NgView). La fonction de compilation a les paramètres suivants:
1.Telement - L'élément de modèle utilise l'élément directif actuel. Il est sûr de simplement effectuer une conversion de modèle sous l'élément actuel ou l'élément de l'élément actuel.
2.Tattrs - Attributs de modèle - Les attributs standardisés, déclarés dans l'élément actuel, peuvent être partagés entre diverses directives. Pour plus de détails, veuillez consulter le chapitre Attributs
3. Transclure une fonction de liaison pour la conversion: fonction (portée, clonelink).
Remarque: Si le modèle a été cloné, l'instance de modèle et l'instance de liaison ne peuvent pas être le même objet. Pour ce faire, il n'est pas sûr de faire autre chose que la conversion DOM dans la fonction de compilation, qui sera appliquée à tous les clones. En particulier, le fonctionnement d'enregistrement de l'écouteur d'événements DOM doit être effectué dans la fonction de liaison, et non dans la fonction de compilation.
La fonction de compilation peut avoir une valeur de retour et le type peut être une fonction ou un objet.
1. La fonction de retour est généralement utilisée lorsque la fonction de compilation n'est pas requise (vide), ce qui équivaut à l'enregistrement d'une fonction de liaison via le lien (définit directement les attributs du modèle).
2. Renvoie un objet contenant des propriétés pré et post - nous permet de contrôler lorsque la fonction de liaison est appelée pendant la phase de liaison. Pour plus de détails, veuillez consulter les chapitres suivants sur les fonctions de pré-alimentation et de post-alimentation.
10. Fonction de liaison
Lien de fonction (Scope, Ielement, Iattrs, Controller) {…}
La fonction de liaison est responsable de l'enregistrement de l'écouteur de l'événement DOM et peut également effectuer des opérations de mise à jour DOM. La fonction de liaison sera exécutée une fois l'opération de clonage de modèle terminée. La majeure partie de la logique de directive est stockée ici.
1.Scope - Scope - est utilisé pour enregistrer les montres (http://docs.angularjs.org/api/ng.$rootscope.scope#$watch).
2.Ielement - instance d'élément - élément utilisé par directive. Il est sûr d'opérer sur des éléments enfants dans la fonction PostLink. Parce que les éléments enfants ont été liés (connectés au modèle ?!).
3.Iattrs - Instance d'attribut - La liste d'attribut de l'élément actuel standard. Partagé entre toutes les fonctions de liaison directive.
4.Contrôleur - Instance de contrôleur - Si l'un des contrôleurs est défini dans la directive de l'élément actuel, vous pouvez obtenir une instance du contrôleur ici. Ce contrôleur est partagé entre toutes les directives, permettant à chaque directive de traiter le contrôleur comme un canal de communication entre eux.
Fonction de pré-liaison
Exécuter avant l'élément enfant lié. Il n'est pas sûr de faire la conversion DOM ici, car la fonction de liaison du compilateur peut ne pas localiser les éléments corrects lors de la liaison.
Fonction post-liaison
Exécuter après l'élément enfant lié. Il est sûr d'effectuer une conversion DOM ici.
11. Attributs
Objet d'attribut - comme arguments dans link () ou compile () - est un moyen d'accéder à ce qui suit:
1. Noms d'attribut standardisés: Parce que la directive, telle que NGBIND, elle peut se manifester sous de nombreuses formes, telles que "ng: bind", "x-ng-bider" ... Cet objet d'attribut nous permet d'accéder aux attributs par nom standard (camel).
2. Communication entre directives: toutes les directives partagent une instance d'objet d'attribut, afin que les directives puissent communiquer entre les directives via des objets d'attribut.
3. Prise en charge de l'interpolation: l'attribut d'interpolation est attribué à un objet d'attribut, permettant à d'autres directives de lire la valeur interpolée.
4. Observer les attributs interpolés: observer les changements dans les valeurs d'attribut via l'attr. $ Observer, y compris l'interpolation (par exemple, src = ”{{bar}}"). Non seulement il est très efficace, mais c'est aussi le seul moyen d'obtenir simplement la valeur réelle. Parce que pendant l'étape de liaison, l'interpolation n'a pas été attribuée (remplacée par la valeur réelle), donc lors de l'accès à l'heure à ce moment, le résultat n'est pas défini.
<! Doctype html> <html lang = "zh-cn" ng-app = "DiretiveProperty"> <adread> <meta charset = "utf-8"> <tight> Directive-Attribute-Test </ title> <style type = "Text / CSS"> .ng-Cloak {Affichage: Aucun; } </ style> </ head> <body ng-controller = "myctrl"> <input type = "text" ng-model = "name" value = "myname" /> <p my-attr = "123" directive-p2 attr-dd = "{{name}}"> </p> <script src = ".. type = "text / javascript"> </ script> <script type = "text / javascript"> var app = angular.module ("DiretiveProperty", []); app.Controller ("myctrl", function ($ scope) {$ scope.name = "My Little Dada";}); Var DiretiveP2 = App.Directive ("DirectiveP2", fonction () {return {link: function postLink (scope, Lele, lattr) {console.log ("myAttr:" + lattr.myattr); // 123 console.log (MyAttr: "+ Lattr.Attrdd); // Undefined Lattr. Console.log ('attdd a changé la valeur de' +);12. Comprendre la transclusion et la portée
Nous avons souvent besoin de composants réutilisables. Voici un pseudo-code montrant comment un composant de dialogue simple peut fonctionner.
<bouton ng-click = "show = true"> show </ button> <dialogue visible = "show" on-cancel = "show = false" on-ok = "show = false; doSomething ()"> body va ici: {{username}} est {{title}}. </ Dialog>Cliquer sur le bouton "Afficher" ouvrira la boîte de dialogue. La boîte de dialogue a un titre lié aux données "nom d'utilisateur", et il y a aussi un paragraphe que nous voulons placer à l'intérieur de la boîte de dialogue.
Ce qui suit est une définition de modèle écrite pour la boîte de dialogue:
<div ng-show = "show ()"> <h3> {{title}} </h3> <div ng-transclude> </div> <div> <Button ng-Click = "OnOk ()"> Enregistrer les modifications </ bouton> <Button ng-Click = "Oncancel ()"> Fermer </ Button> </div> </div>Cela ne rendra pas correctement à moins que nous effectuons un traitement spécial sur la portée.
Le premier problème que nous devons résoudre est que le modèle de dialogue s'attend à ce que le titre soit défini et sera lié au nom d'utilisateur lors de l'initialisation. De plus, le bouton nécessite deux fonctions onok et oncancel pour apparaître dans la portée. Cela limite l'utilité du widget ..). Pour résoudre le problème de cartographie, les variables locales attendues par le modèle sont créées par les méthodes locales suivantes (les habitants, qui est estimé être la portée du modèle de définition directive):
SPOPE: {Title: 'Bind', // Configurer le titre pour accepter la liaison des données ONOK: 'Expression', // Créer une fonction ONOK ONOK ONOK Oncancel: 'Expression', // Créer une fonction Oncancel de délégué Show: 'Accessor' // Créer une fonction Getter / Setter pour la visibilité.}.La création de propriétés locales dans la portée de contrôle apporte deux problèmes:
1. Isolation (Attribut Isolation?) - Si l'utilisateur oublie de définir le titre d'attribut d'élément dans le modèle de contrôle, le titre sera lié à l'attribut "titre" de la portée de l'ancêtre (le cas échéant). C'est imprévisible et indésirable.
2. Transclusion - Dom traduit peut afficher les habitants (portée de l'isolat?) Du contrôle. Les habitants remplaceront les propriétés qui doivent vraiment être liées dans la transclusion. Dans notre exemple, la propriété de titre du plugin détruit la propriété de titre de la transclusion.
Pour résoudre ce problème de manque d'isolement d'attribut, nous devons définir une portée isolée pour cette directive. La portée isolée n'est pas héritée du prototype de la portée de l'enfant (pourquoi est-ce la portée des enfants? n'est-ce pas la portée des parents?) Nous n'avons donc pas à nous soucier des problèmes de conflit d'attribut (en tant que frère de la portée actuelle).
Cependant, la portée isolée apporte un nouveau problème: si un DOM traduit est un enfant de la portée isolée du widget, il ne pourra rien lier à quoi que ce soit. Par conséquent, la portée traduite est une portée enfant de la portée originale créée avant le contrôle crée la portée isolée de la propriété locale. La portée traduite et isolée appartiennent au nœud de frère (dans l'arbre de la lunette).
Cela peut sembler un peu compliqué de manière inattendue, mais cela apporte au moins des surprises pour contrôler les utilisateurs et contrôler les développeurs. (Le problème a été résolu)
Par conséquent, la définition de directive finale est à peu près la suivante:
transclude: true, scope: {title: 'bind', // configurer le titre pour accepter la contrainte de données onok: 'expression', // créer une fonction ONOK déléguée oncancel: 'expression', // créer une fonction oncancel déléguée: 'accessor' // Créer une fonction Getter / Setter pour la visibilité. // J'ai essayé cela, mais ça a échoué ... Veuillez continuer à lire}J'ai essayé de reconstituer le code ci-dessus dans un exemple complet. Si vous copiez directement, les résultats attendus ne seront pas obtenus. Mais après une petite modification, le plug-in peut être exécuté.
<! Doctype html> <html ng-app = "Dialog"> <éad> <méta http-equiv = "contenu-type" contenu = "text / html; charset = utf-8" /> <title> directive-dialog </ title> <méta contenu = "ie = edge, chrome = 1" http-equiv = "x-ua-compatble"> <script = 1 "http-equiv =" x-ua-compatble "> <script = 1" http-equiv = "x-ua-compable src = "../ angular.js" type = "text / javascript"> </ script> </ head> <body> <div ng-controller = "myctrl"> <button ng-Click = "show = true"> show </ bouton> <dialogue visible = "{{show}}" on-cancel = "show = false;" on-ok = "show = false; methodinparentscope ();"> <! - Le canal et le canal ci-dessus sont référencés par et dans la portée isolée de la directive. Si l'expression contient une fonction, vous devez lier la fonction dans la portée du parent (actuellement MyCtrl Scope) -> Body va ici: nom d'utilisateur: {{nom d'utilisateur}}, titre: {{title}}. <ul> <! - Vous pouvez également jouer comme ceci ici ~ Les noms sont Parent Scope -> <li ng-repeat = "Name in Names"> {{name}} </li> </ul> </ dialog> </ div> <script type = "Text / Javascript"> var myModule = angular.module ("Dialog", []); MyModule.Controller ("myctrl", fonction ($ scope) {$ scope.Names = ["name1", "name2", "name3"]; $ scope.show = false; $ scope.userName = "lclao"; $ scope.title = "Title parent"; $ Scope.MethodInparentScope = fonction () {alert ("". joué dans la portée des parents !!! ");};}); mymodule.directive ('dialogue', fonction factory () {return {priority: 100, modèle: ['<div ng-show = "visible">', '<h3> {{title}} </h3>', '<div ng-transclude> </v>', '<div>', '<bouton ng-Click = "OnOk ()" ng-click = "oncancel ()"> close </utton> ',' </div> ',' </div> ',' </div> ']. join (""), remplacer: false, transclude: true, restreindre:' e ', scope: {title: "@", // cible la valeur de l'attribut de dialogue de la boîte de dialogue Dans la forme de la fonction de wrapper Oncancel: "&", // Utiliser la fonction de la fonction de wrapper fait référence au contenu de la propriété de la boîte de dialogue visible: "@" // fait référence à la valeur de la propriété visible de la balise de dialogue}}; </cript> </ body> </html>13. Créer des composants
Nous nous attendons généralement à remplacer la directive via une structure DOM complexe (l'élément est situé? Le but est probablement de faire de la directive des points complexes internes, qui ont l'air génial @ _ @). Cela fait de la directive un raccourci vers la création d'applications à l'aide de composants réutilisables.
Voici un exemple de composant réutilisable:
<! Doctype html> <html ng-app = "zippymodule"> <éad> <méta http-equiv = "tent-type" contenu = "text / html; charset = utf-8" /> <itle> zippymodule </ title> <méta contenu = "ie = edge, chrome = 1" http-equie <style type = "text / css"> .zippy {border: 1px solide noir; Affichage: bloc en ligne; Largeur: 250px; } .zippy.opened> .title: avant {contenu: ''; } .zippy.openened> .body {display: block; } .zippy.closed> .title: avant {contenu: '►'; } .zippy.closed > .body { display: none; } .zippy > .title { background-color: black; color: white; padding: .1em .3em; curseur: pointeur; } .zippy > .body { padding: .1em .3em; } </style> <script src="../angular.js" type="text/javascript"></script></head><body> <div ng-controller="MyCtrl"> Title: <input ng-model="title" type="text"><br/> Text: <textarea ng-model="text"></textarea> <hr/> <div zippy-title="Details: {{title}}...">{{text}}</div> </div> <script type="text/javascript"> var myModule = angular.module("ZippyModule", []); myModule.controller("MyCtrl", function ($scope) { $scope.title = "Here is the title"; $scope.text = "Here is the content... "; }); myModule.directive('zippy', function () { return { template: '<div>' + ' <div>{{title}}</div>' +//This title belongs to the property of the current direct isolate scope ' <div ng-transclude></div>' + //What is here, what is obtained is the property of the parent scope '</div>', replace:true, transclude: true, restrict:'C', scope:{ title:"@zippyTitle"//Bind the zippy-title attribute on the directive element}, link:function(scope,element,attrs) { var title = angular.element(element.children()[0]), opened = false; title.bind("click", toogle); element.addClass("closed"); function toogle() { opened = !opened; element.removeClass(opened ? "closed" : "opened"); element.addClass(opened ? "opened" : "closed"); } } }; }); </script></body></html>