Je dois effectuer certaines opérations sur le scope et le template. Il semble que je puisse le faire dans la fonction link
ou dans la fonction controller
(puisque les deux ont accès à la portée).
À quel moment dois-je utiliser la fonction link
et non le contrôleur?
angular.module('myApp').directive('abc', function($timeout) {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: true,
link: function(scope, elem, attr) { /* link function */ },
controller: function($scope, $element) { /* controller function */ }
};
}
De plus, je comprends que link
est le monde non angulaire. Donc, je peux utiliser $watch
, $digest
et $apply
.
Quelle est la signification de la fonction link
alors que nous avions déjà un contrôleur?
Après mes luttes initiales avec les fonctions link
et controller
et en en lisant beaucoup, je pense que j’ai maintenant le répondre.
Commençons par à comprendre ,
Comment fonctionnent les directives angular en quelques mots:
Nous commençons avec un modèle (sous forme de chaîne ou chargé dans une chaîne)
var templateString = '<div my-directive>{{5 + 10}}</div>';
Maintenant, cette templateString
est enveloppée comme un élément angulaire
var el = angular.element(templateString);
Avec el
, nous le compilons maintenant avec $compile
pour récupérer la fonction link .
var l = $compile(el)
Voici ce qui se passe,
$compile
parcourt l'intégralité du modèle et collecte toutes les directives qu'il reconnaît.link
sont collectées.link
sont encapsulées dans une nouvelle fonction link
et renvoyées sous la forme l
.Enfin, nous fournissons la fonction scope
à cette fonction l
(lien) qui exécute ensuite les fonctions de lien encapsulées avec ce scope
et leurs éléments correspondants.
l(scope)
Ceci ajoute la template
comme nouveau nœud à la DOM
et appelle controller
qui ajoute ses surveillances à la portée qui est partagé avec le modèle dans DOM.
Comparer compiler vs lien vs contrôleur :
Chaque directive est compilée une seule fois et la fonction link est conservée pour utilisation. Par conséquent, s'il existe quelque chose qui s'applique à toutes les instances d'une directive, cela doit être effectué dans la fonction compile
de la directive.
Maintenant, après la compilation, nous avons la fonction link
qui est exécutée tout en attachant le template au DOM. Nous effectuons donc tout ce qui est spécifique à chaque instance de la directive. Par exemple: attacher des événements , transformer le modèle en fonction de la portée , etc. .
Enfin, le contrôleur doit être disponible pour être actif et réactif pendant que la directive fonctionne sur la DOM
(après avoir été attaché). Donc:
(1) Après avoir configuré la vue [V] (c'est-à-dire un modèle) avec un lien. $scope
est notre [M] et $controller
est notre [C] dans MVC
(2) Profitez de la liaison à 2 voies avec $ scope en mise en place des montres.
(3) $scope
on s'attend à ce que des montres soient ajoutées au contrôleur car c'est ce qui surveille le modèle pendant l'exécution.
(4) Enfin, controller
est également utilisé pour pouvoir communiquer entre les directives associées. (Comme myTabs
exemple dans https://docs.angularjs.org/guide/directive )
(5) Il est vrai que nous aurions pu faire tout cela dans la fonction link
, mais il en va de même la séparation des problèmes .
Par conséquent, enfin, nous avons ce qui suit qui convient parfaitement à toutes les pièces:
La différence entre link
et controller
entre en jeu lorsque vous souhaitez imbriquer des directives dans votre DOM et exposer des fonctions API de la directive parente à celles imbriquées.
De la docs :
Meilleure pratique: utilisez le contrôleur lorsque vous souhaitez exposer une API à d'autres directives. Sinon, utilisez le lien.
Supposons que vous souhaitiez avoir deux directives my-form
et my-text-input
et que vous souhaitiez que la directive my-text-input
n'apparaisse que dans my-form
et nulle part ailleurs.
Dans ce cas, vous direz lors de la définition de la directive my-text-input
qu'elle requiert un contrôleur de l'élément DOM parent
à l'aide de l'élément require
argument , comme ceci: require: '^myForm'
. Maintenant, le contrôleur de l'élément parent sera injected
dans la fonction link
en tant que quatrième argument, après $scope, element, attributes
. Vous pouvez appeler des fonctions sur ce contrôleur et communiquer avec la directive parent.
De plus, si un tel contrôleur n'est pas trouvé, une erreur sera générée.
Il n’est pas vraiment nécessaire d’utiliser la fonction link
si l’on définit le controller
puisque le $scope
est disponible sur le controller
. De plus, lors de la définition de link
et de controller
, il convient de faire attention à l'ordre d'invocation des deux (controller
est exécuté auparavant).
Cependant, conformément à la méthode angulaire , la plupart des manipulations DOM et des liaisons bidirectionnelles à l'aide de $watchers
sont généralement effectuées dans la fonction link
, tandis que L'API pour les enfants et la manipulation de $scope
se font dans le controller
. Ce n'est pas une règle absolue, mais cela rendra le code plus modulaire et facilitera la séparation des problèmes (le contrôleur conservera l'état directive
et la fonction link
conservera les liaisons DOM
+ extérieures).
La fonction/objet controller
représente un contrôleur d'abstraction modèle-vue-contrôleur (MVC). Bien qu’il n’y ait rien de nouveau à écrire sur MVC, c’est toujours l’avantage le plus significatif d’angularité: diviser les préoccupations en plusieurs parties. Et voilà, rien de plus, donc si vous devez réagir sur Model
changements venant de View
la Controller
est la bonne personne à faire ce travail.
L'histoire de la fonction link
est différente, elle vient d'une perspective différente de celle de MVC. Et est vraiment essentiel, une fois que nous voulons franchir les limites d'un controller/model/view
(modèle) .
Commençons par les paramètres passés dans la fonction link
:
function link(scope, element, attrs) {
Pour placer la link
dans le contexte, il convient de mentionner que toutes les directives suivent cette étape du processus d’initialisation: Compile , Lien . Un extrait de livre de Brad Green et Shyam Seshadri Angular JS :
Phase de compilation (une soeur de link, mentionnons-le ici pour avoir une image claire):
Au cours de cette phase, Angular guide le DOM pour identifier toutes les directives enregistrées dans le modèle. Pour chaque directive, il transforme ensuite le DOM en fonction des règles de celle-ci (template, replace, transclude, etc.) et appelle la fonction de compilation si elle existe. Le résultat est une fonction de modèle compilée,
Phase de liaison :
Pour rendre la vue dynamique, Angular exécute ensuite une fonction de lien pour chaque directive. Les fonctions de lien créent généralement des écouteurs sur le DOM ou le modèle. Ces auditeurs gardent la vue et le modèle synchronisés à tout moment.
Voici un exemple intéressant d'utilisation de la variable link
: Création de directives personnalisées . Voir l'exemple: Création d'une directive manipulant le DOM , qui insère une "date-heure" dans la page, actualisée toutes les secondes.
Juste un très court extrait de la source riche ci-dessus, montrant la véritable manipulation avec DOM. Il y a une fonction accrochée au service $ timeout et elle est également effacée dans son appel destructor pour éviter les fuites de mémoire.
.directive('myCurrentTime', function($timeout, dateFilter) {
function link(scope, element, attrs) {
...
// the not MVC job must be done
function updateTime() {
element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM
}
function scheduleUpdate() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
scheduleUpdate(); // schedule the next update
}, 1000);
}
element.on('$destroy', function() {
$timeout.cancel(timeoutId);
});
...