Lien vs compiler vs controller

lorsque vous créez une directive, vous pouvez mettre du code dans le compilateur, la fonction de lien ou le contrôleur.

dans les docs, ils expliquent que:

  • fonction de compilation et de lien sont utilisés dans différentes phases de l'angle cycle
  • les contrôleurs sont partagés entre les directives

Cependant, pour moi, il n'est pas clair, quel genre de code devrait aller où.

Par exemple: Puis-je créer des fonctions dans la compilation et les avoir attachées au scope dans link ou seulement attacher des fonctions au scope dans le controller?

comment les contrôleurs sont-ils répartis entre les directives, si chaque directive peut avoir son propre contrôleur? Les controllers sont-ils réellement partagés ou s'agit-il seulement des propriétés scope?

512
demandé sur BSMP 2013-03-28 11:48:54

6 réponses

compiler:

c'est la phase où Angular compile réellement votre directive. Cette fonction de compilation n'est appelée qu'une fois pour chaque référence à la directive donnée. Par exemple, supposons que vous utilisez la directive ng-repeat. ng-repeat devra rechercher l'élément auquel il est attaché, extraire le fragment html auquel il est attaché et créer une fonction de modèle.

si vous avez utilisé un guidon, soulignez templates ou l'équivalent, c'est comme compiler leurs templates pour extraire une fonction de template. Pour cette fonction de modèle vous passez des données et la valeur de retour de cette fonction est le html avec les données aux bons endroits.

la phase de compilation est cette étape en angle qui renvoie la fonction template. Cette fonction de gabarit en angle est appelée la fonction de liaison.

Reliant la phase :

La phase de lien est où vous attachez les données ($scope ) à la fonction de lien et il devrait vous retourner le html lié. Puisque la directive spécifie également où ce html va ou ce qu'il change, il est déjà bon d'aller. C'est la fonction où vous voulez apporter des modifications au html, I. e le html qui contient déjà les données. En angle si vous écrivez le code dans la fonction de liaison son généralement la fonction de post-lien (par défaut). Il est une sorte de callback qui est appelée à après la fonction de liaison a lié les données avec le modèle.

contrôleur:

le controller est un endroit où vous mettez une logique spécifique à une directive. Cette logique peut aller dans la fonction de lien aussi bien, mais alors vous devriez mettre cette logique sur la portée pour la rendre "partageable". Le problème, c'est que vous pervertissiez alors le champ d'application de vos directives, ce qui n'est pas vraiment quelque chose que est prévu. Quelle est donc l'alternative si deux Directives veulent se parler / coopérer? Bien sûr, vous pourriez mettre toute cette logique dans un service et ensuite faire dépendre ces deux directives de ce service, mais cela n'apporte qu'une dépendance de plus. L'alternative est de fournir un Contrôleur pour cette portée ( généralement isoler portée ? ) puis ce contrôleur est injecté dans une autre directive lorsque celle-ci "requiert" l'autre. Voir les onglets et les vitres sur le premier page de angularjs.org pour un exemple.

458
répondu ganaraj 2014-09-30 11:36:24

je voulais ajouter aussi ce que le livre O'Reily AngularJS de L'équipe de Google a à dire:

Contrôleur - Créer un contrôleur qui publie une API pour communiquer au-delà des directives. Un bon exemple est Directive à la Communication de Directive

Lien - modifier par programmation résultant de l'élément DOM cas, ajouter des écouteurs d'événement, et de configurer la liaison de données.

compiler - Modifier programmatiquement le modèle DOM pour les fonctionnalités à travers les copies d'une directive, comme lorsqu'il est utilisé dans ng-repeat. Votre fonction de compilation peut également renvoyer des fonctions de lien pour modifier les instances d'éléments résultantes.

96
répondu Nicholas Dynan 2016-01-21 15:31:23

A directive vous permet d'étendre le vocabulaire HTML d'une manière déclarative pour la construction de composants web. L'attribut ng-app est une directive, ainsi que ng-controller et tout le ng- prefixed attributes . Les Directives peuvent être attributes , tags ou même class names , comments .

comment les directives naissent ( compilation et instantiation )

compiler: nous allons utiliser le compile fonction à la fois manipulate le DOM avant qu'il soit rendu et retourner une fonction link (qui gérera la liaison pour nous). C'est également l'endroit pour mettre toutes les méthodes qui doivent être partagées avec l'ensemble des instances de cette directive.

lien: nous allons utiliser la fonction link pour enregistrer tous les écouteurs sur un élément DOM spécifique (qui est cloné à partir du modèle) et configurer nos fixations à la page.

si elles étaient définies dans la fonction compile() , elles n'auraient été définies qu'une seule fois (ce qui est souvent ce que vous voulez). Si elles sont définies dans la fonction link() , elles seront définies chaque fois que L'élément HTML est lié aux données de l'objet .

<div ng-repeat="i in [0,1,2]">
    <simple>
        <div>Inner content</div>
    </simple>
</div>

app.directive("simple", function(){
   return {
     restrict: "EA",
     transclude:true,
     template:"<div>{{label}}<div ng-transclude></div></div>",        
     compile: function(element, attributes){  
     return {
             pre: function(scope, element, attributes, controller, transcludeFn){

             },
             post: function(scope, element, attributes, controller, transcludeFn){

             }
         }
     },
     controller: function($scope){

     }
   };
});

Compile renvoie la fonction de lien pre et post . Dans la fonction pre link nous avons le modèle d'instance et aussi le scope du controller , mais pourtant, le modèle n'est pas lié à la portée et n'a toujours pas transclusionné le contenu.

Post fonction de lien est l'endroit où afficher le lien est la dernière fonction à exécuter. Maintenant le transclusion est complet, the template is linked to a scope , et le view will update with data bound values after the next digest cycle . L'option link n'est qu'un raccourci pour configurer une fonction post-link .

contrôleur: le contrôleur de directive peut être passé à une autre directive Phase de liaison / compilation. Il peut être injecté dans d'autres directions comme un moyen à utiliser dans la communication inter-directive.

vous devez spécifier le nom de la directive à exiger – elle doit être liée au même élément ou à son parent. Le nom peut être préfixé avec:

? – Will not raise any error if a mentioned directive does not exist.
^ – Will look for the directive on parent elements, if not available on the same element.

utiliser le support carré [‘directive1′, ‘directive2′, ‘directive3′] pour exiger le contrôleur de directives multiples.

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope, $element) {
});

app.directive('parentDirective', function() {
  return {
    restrict: 'E',
    template: '<child-directive></child-directive>',
    controller: function($scope, $element){
      this.variable = "Hi Vinothbabu"
    }
  }
});

app.directive('childDirective', function() {
  return {
    restrict:  'E',
    template: '<h1>I am child</h1>',
    replace: true,
    require: '^parentDirective',
    link: function($scope, $element, attr, parentDirectCtrl){
      //you now have access to parentDirectCtrl.variable
    }
  }
});
47
répondu Thalaivar 2015-09-29 14:07:00

en outre, une bonne raison d'utiliser une fonction controller vs. link (puisqu'ils ont tous les deux accès à la portée, l'élément, et attrs) est parce que vous pouvez passer dans n'importe quel service disponible ou dépendance dans un controller (et dans n'importe quel ordre), alors que vous ne pouvez pas le faire avec la fonction link. Remarquez les différentes signatures:

controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...

vs.

link: function(scope, element, attrs) {... //no services allowed
10
répondu ScaryBunny 2013-11-07 15:47:07

c'est un bon exemple pour comprendre les phases de la directive http://codepen.io/anon/pen/oXMdBQ?editors=101

var app = angular.module('myapp', [])

app.directive('slngStylePrelink', function() {
    return {
        scope: {
            drctvName: '@'
        },
        controller: function($scope) {
            console.log('controller for ', $scope.drctvName);
        },
        compile: function(element, attr) {
            console.log("compile for ", attr.name)
            return {
                post: function($scope, element, attr) {
                    console.log('post link for ', attr.name)
                },
                pre: function($scope, element, attr) {
                    $scope.element = element;
                    console.log('pre link for ', attr.name)
                        // from angular.js 1.4.1
                    function ngStyleWatchAction(newStyles, oldStyles) {
                        if (oldStyles && (newStyles !== oldStyles)) {
                            forEach(oldStyles, function(val, style) {
                                element.css(style, '');
                            });
                        }
                        if (newStyles) element.css(newStyles);
                    }

                    $scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);

                    // Run immediately, because the watcher's first run is async
                    ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
                }
            };
        }
    };
});

html

<body ng-app="myapp">
    <div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
        <div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
        </div>
    </div>
</body>
9
répondu Amin Rahimi 2015-07-18 15:28:54
  • compiler : utilisé lorsque nous avons besoin de modifier le modèle de directive, comme ajouter une nouvelle expression, ajouter une autre directive à l'intérieur de cette directive
  • controller : utilisé lorsque nous avons besoin de partager/réutiliser $scope data
  • link : il s'agit d'une fonction utilisée lorsque nous avons besoin d'attacher le gestionnaire d'événements ou de manipuler le DOM.
2
répondu HamidKhan 2017-06-22 15:09:45