Directives angulars – quand et comment utiliser la compilation, le contrôleur, le pré-lien et le post-lien

Lors de l’écriture d’une directive angular, on peut utiliser l’une des fonctions suivantes pour manipuler le comportement, le contenu et l’apparence du DOM sur lequel la directive est déclarée:

  • comstackr
  • manette
  • pré-lien
  • post-lien

Il semble y avoir une certaine confusion quant à la fonction à utiliser. Cette question couvre:

Principes de base de la directive

  • Comment déclarer les différentes fonctions?
  • Quelle est la différence entre un modèle source et un modèle d’instance ?
  • Dans quel ordre les fonctions de la directive sont-elles exécutées?
  • Que se passe-t-il entre ces appels de fonction?

Fonction nature, faire et ne pas faire

  • Comstackr
  • Manette
  • Pré-lien
  • Post-lien

Questions connexes:

  • Directive: lien vs compilation vs contrôleur .
  • Différence entre les fonctions ‘controller’, ‘link’ et ‘comstack’ lors de la définition d’une directive angular.js .
  • Quelle est la différence entre la fonction de compilation et la fonction de lien dans angularjs .
  • Différence entre l’élément pré-compilation et post-compilation dans les directives AngularJS? .
  • Directive angular JS – Modèle, compilation ou lien? .
  • post link vs pre link dans les directives angulars js .

Dans quel ordre les fonctions de la directive sont-elles exécutées?

Pour une seule directive

Basé sur le plunk suivant, considérez le balisage HTML suivant:

 

Avec la déclaration de directive suivante:

 myApp.directive('log', function() { return { controller: function( $scope, $element, $attrs, $transclude ) { console.log( $attrs.log + ' (controller)' ); }, comstack: function comstack( tElement, tAtsortingbutes ) { console.log( tAtsortingbutes.log + ' (comstack)' ); return { pre: function preLink( scope, element, atsortingbutes ) { console.log( atsortingbutes.log + ' (pre-link)' ); }, post: function postLink( scope, element, atsortingbutes ) { console.log( atsortingbutes.log + ' (post-link)' ); } }; } }; }); 

La sortie de la console sera:

 some-div (comstack) some-div (controller) some-div (pre-link) some-div (post-link) 

Nous pouvons voir que la comstack est exécutée en premier, puis le controller , puis le pre-link et le dernier est post-link .

Pour les directives nestedes

Remarque: Ce qui suit ne s’applique pas aux directives qui rendent leurs enfants dans leur fonction de lien. De nombreuses directives angulars le font (comme ngIf, ngRepeat ou toute directive avec transclude ). Ces directives auront nativement leur fonction de link appelée avant que leur comstack enfant ne soit appelée.

Le balisage HTML d’origine est souvent composé d’éléments nesteds, chacun avec sa propre directive. Comme dans le balisage suivant (voir plunk ):

  

La sortie de la console ressemblera à ceci:

 // The comstack phase parent (comstack) ..first-child (comstack) ..second-child (comstack) // The link phase parent (controller) parent (pre-link) ..first-child (controller) ..first-child (pre-link) ..first-child (post-link) ..second-child (controller) ..second-child (pre-link) ..second-child (post-link) parent (post-link) 

On peut distinguer ici deux phases – la phase de compilation et la phase de liaison .

La phase de compilation

Lorsque le DOM est chargé, Angular démarre la phase de compilation, où il parcourt le balisage, et les appels sont comstack sur toutes les directives. Graphiquement, nous pourrions l’exprimer ainsi:

Une image illustrant la boucle de compilation pour les enfants

Il est peut-être important de mentionner qu’à ce stade, les modèles obtenus par la fonction de compilation sont les modèles source (et non le modèle d’instance).

La phase de liaison

Les instances DOM sont souvent simplement le résultat d’un modèle source rendu dans le DOM, mais elles peuvent être créées par ng-repeat ou introduites à la volée.

Chaque fois qu’une nouvelle instance d’un élément avec une directive est rendue dans le DOM, la phase de liaison commence.

Dans cette phase, Angular appelle le controller , pre-link , itère les enfants et appelle post-link sur toutes les directives, comme ceci:

Une illustration illustrant les étapes de la phase de liaison

Que se passe-t-il entre ces appels de fonction?

Les différentes fonctions directives sont exécutées depuis deux autres fonctions angulars appelées $comstack (où la $comstack la directive est exécutée) et une fonction interne appelée nodeLinkFn (où le controller la directive, preLink et postLink sont exécutés). Diverses choses se produisent dans la fonction angular avant et après l’appel des fonctions de la directive. Peut-être plus particulièrement la récursivité de l’enfant. L’illustration simplifiée suivante montre les étapes clés des phases de compilation et de liaison:

Une illustration montrant les phases de compilation et de liaison angulaires

Pour illustrer ces étapes, utilisons le balisage HTML suivant:

 
Inner content

Avec la directive suivante:

 myApp.directive( 'myElement', function() { return { ressortingct: 'EA', transclude: true, template: '
{{label}}
' } });

Comstackr

L’API de comstack ressemble à ceci:

 comstack: function comstack( tElement, tAtsortingbutes ) { ... } 

Les parameters sont souvent préfixés par t pour indiquer que les éléments et les atsortingbuts fournis sont ceux du modèle source, plutôt que ceux de l’instance.

Avant l’appel à comstack contenu exclu (le cas échéant) est supprimé et le modèle est appliqué au balisage. Ainsi, l’élément fourni à la fonction de comstack ressemblera à ceci:

  
"{{label}}"

Notez que le contenu exclu n’est pas réinséré à ce stade.

Suite à l’appel à la

Création d’instance

Dans notre cas, trois instances du modèle source ci-dessus seront créées (par ng-repeat ). Ainsi, la séquence suivante s’exécutera trois fois, une fois par instance.

Manette

L’API du controller implique:

 controller: function( $scope, $element, $attrs, $transclude ) { ... } 

En entrant dans la phase de liaison, la fonction de lien renvoyée via $comstack est maintenant fournie avec une scope.

Tout d’abord, la fonction de lien crée une étendue enfant ( scope: true ) ou une scope isolée ( scope: {...} ) si nécessaire.

Le contrôleur est alors exécuté, fourni avec la scope de l’élément d’instance.

Pré-lien

L’API de pre-link ressemble à ceci:

 function preLink( scope, element, atsortingbutes, controller ) { ... } 

Pratiquement rien ne se passe entre l’appel à la directive .controller et la fonction .preLink . Angular recommande toujours comment chacun doit être utilisé.

Après l’appel de .preLink , la fonction de liaison va parcourir chaque élément enfant – en appelant la fonction de lien correcte et en lui attachant l’étendue actuelle (qui sert d’étendue parent pour les éléments enfants).

Post-lien

L’API post-link est similaire à celle de la fonction de pre-link :

 function postLink( scope, element, atsortingbutes, controller ) { ... } 

Cela vaut peut-être la peine de noter qu’une fois la fonction

Cela signifie que, au moment où .postLink est appelé, les enfants sont «en direct» et prêts. Ceci comprend:

  • liaison de données
  • transclusion appliquée
  • scope attachée

Le modèle à ce stade ressemblera donc à ceci:

  
"{{label}}"
Inner content

Comment déclarer les différentes fonctions?

Comstackr, Contrôler, Pré-lien et Post-lien

Si l’on doit utiliser les quatre fonctions, la directive suivra cette forme:

 myApp.directive( 'myDirective', function () { return { ressortingct: 'EA', controller: function( $scope, $element, $attrs, $transclude ) { // Controller code goes here. }, comstack: function comstack( tElement, tAtsortingbutes, transcludeFn ) { // Comstack code goes here. return { pre: function preLink( scope, element, atsortingbutes, controller, transcludeFn ) { // Pre-link code goes here }, post: function postLink( scope, element, atsortingbutes, controller, transcludeFn ) { // Post-link code goes here } }; } }; }); 

Notez que la compilation retourne un object contenant à la fois les fonctions pré-lien et post-lien; Dans le jargon angular, nous disons que la fonction de compilation retourne une fonction de modèle .

Comstackr, Contrôler et Post-lien

Si le pre-link n’est pas nécessaire, la fonction de compilation peut simplement renvoyer la fonction post-lien au lieu d’un object de définition, comme ceci:

 myApp.directive( 'myDirective', function () { return { ressortingct: 'EA', controller: function( $scope, $element, $attrs, $transclude ) { // Controller code goes here. }, comstack: function comstack( tElement, tAtsortingbutes, transcludeFn ) { // Comstack code goes here. return function postLink( scope, element, atsortingbutes, controller, transcludeFn ) { // Post-link code goes here }; } }; }); 

Parfois, on souhaite append une méthode de comstack , après la définition de la méthode (post) de link . Pour cela, on peut utiliser:

 myApp.directive( 'myDirective', function () { return { ressortingct: 'EA', controller: function( $scope, $element, $attrs, $transclude ) { // Controller code goes here. }, comstack: function comstack( tElement, tAtsortingbutes, transcludeFn ) { // Comstack code goes here. return this.link; }, link: function( scope, element, atsortingbutes, controller, transcludeFn ) { // Post-link code goes here } }; }); 

Contrôleur et post-lien

Si aucune fonction de compilation n’est nécessaire, on peut ignorer complètement sa déclaration et fournir la fonction post-link sous la propriété link de l’object de configuration de la directive:

 myApp.directive( 'myDirective', function () { return { ressortingct: 'EA', controller: function( $scope, $element, $attrs, $transclude ) { // Controller code goes here. }, link: function postLink( scope, element, atsortingbutes, controller, transcludeFn ) { // Post-link code goes here }, }; }); 

Pas de contrôleur

Dans l’un des exemples ci-dessus, on peut simplement supprimer la fonction du controller si cela n’est pas nécessaire. Ainsi, par exemple, si seule la post-link est nécessaire, on peut utiliser:

 myApp.directive( 'myDirective', function () { return { ressortingct: 'EA', link: function postLink( scope, element, atsortingbutes, controller, transcludeFn ) { // Post-link code goes here }, }; }); 

Quelle est la différence entre un modèle source et un modèle d’instance ?

Le fait que Angular autorise la manipulation DOM signifie que le balisage d’entrée dans le processus de compilation diffère parfois de la sortie. En particulier, certaines balises d’entrée peuvent être clonées plusieurs fois (comme avec ng-repeat ) avant d’être rendues dans le DOM.

La terminologie angular est un peu incohérente, mais elle distingue encore deux types de balises:

  • Modèle source – le balisage à cloner, si nécessaire. S’il est cloné, ce balisage ne sera pas rendu au DOM.
  • Modèle d’instance – le balisage réel à rendre au DOM. Si le clonage est impliqué, chaque instance sera un clone.

Le balisage suivant montre ceci:

 
{{i}}

Le HTML source définit

  {{i}} 

qui sert de modèle de source.

Mais comme il est encapsulé dans une directive ng-repeat , ce modèle source sera cloné (3 fois dans notre cas). Ces clones sont des modèles d’instance, chacun apparaîtra dans le DOM et sera lié à la scope concernée.

Fonction de compilation

La fonction de comstack chaque directive est appelée une seule fois, lorsque les bootstrap angulars.

Officiellement, c’est l’endroit où effectuer des manipulations de modèles (sources) qui n’impliquent ni scope ni liaison de données.

Principalement, cela est fait à des fins d’optimisation; considérez le balisage suivant:

    

La directive rendra un ensemble particulier de balisage DOM. Nous pouvons donc soit:

  • Autorisez ng-repeat à dupliquer le modèle source ( ), puis modifiez le balisage de chaque modèle d’instance (en dehors de la fonction de comstack ).
  • Modifiez le modèle source pour impliquer le marquage souhaité (dans la fonction de comstack ), puis autorisez ng-repeat à le dupliquer.

S’il y a 1000 éléments dans la collection raws , la dernière option peut être plus rapide que la précédente.

Faire:

  • Manipuler le balisage pour qu’il serve de modèle aux instances (clones).

Ne pas

  • Joindre des gestionnaires d’événements.
  • Inspectez les éléments enfants.
  • Mettre en place des observations sur les atsortingbuts.
  • Mettre en place des montres sur la scope.

Fonction post-lien

Lorsque la post-link est appelée, toutes les étapes précédentes ont eu lieu – liaison, transclusion, etc.

Ceci est typiquement un endroit pour manipuler davantage le DOM rendu.

Faire:

  • Manipuler des éléments DOM (rendus et instanciés).
  • Joindre des gestionnaires d’événements.
  • Inspectez les éléments enfants.
  • Mettre en place des observations sur les atsortingbuts.
  • Mettre en place des montres sur la scope.

Fonction de contrôleur

La fonction de controller chaque directive est appelée chaque fois qu’un nouvel élément associé est instancié.

Officiellement, la fonction de controller est celle où:

  • Définit la logique du contrôleur (méthodes) pouvant être partagée entre les contrôleurs.
  • Initie les variables de scope.

Encore une fois, il est important de se rappeler que si la directive implique une étendue isolée, les propriétés qui en héritent ne sont pas encore disponibles.

Faire:

  • Définir la logique du contrôleur
  • Initier des variables de scope

Ne pas:

  • Inspectez les éléments enfants (ils peuvent ne pas encore être rendus, liés à la scope, etc.).

Fonction de pré-lien

La fonction de pre-link chaque directive est appelée chaque fois qu’un nouvel élément associé est instancié.

Comme vu précédemment dans la section d’ordre de compilation, pre-link fonctions de pre-link sont appelées parent-alors-enfant, alors que les post-link sont appelées child-then-parent .

La fonction de pre-link est rarement utilisée, mais peut être utile dans des scénarios spéciaux; Par exemple, lorsqu’un contrôleur enfant s’enregistre auprès du contrôleur parent, mais que l’enregistrement doit être de type parent-then-child ( ngModelController fait les choses de cette façon).

Ne pas:

  • Inspectez les éléments enfants (ils peuvent ne pas encore être rendus, liés à la scope, etc.).