JS angulaire :Quel est le besoin de la fonction de lien de la directive alors que nous avions déjà le contrôleur de la directive avec une portée ?
-
21-12-2019 - |
Question
Je dois effectuer certaines opérations sur la portée et le modèle.Il semble que je puisse le faire soit dans link
fonction ou le controller
fonction (puisque les deux ont accès à la portée).
Quand dois-je utiliser link
fonction et pas 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 */ }
};
}
Aussi, je comprends que link
est le monde non angulaire.Donc, je peux utiliser $watch
, $digest
et $apply
.
Quelle est la signification du link
fonction, alors qu'on avait déjà un contrôleur ?
La solution
Après mon initial lutter avec le link
et controller
fonctions et en lisant beaucoup à leur sujet, je pense que j'ai maintenant la réponse.
Tout d'abord, permettons comprendre,
Comment fonctionnent les directives angulaires en un mot :
Nous commençons par un modèle (sous forme de chaîne ou chargé dans une chaîne)
var templateString = '<div my-directive>{{5 + 10}}</div>';
Maintenant ça
templateString
est enveloppé comme un élément angulairevar el = angular.element(templateString);
Avec
el
, maintenant nous le compilons avec$compile
pour récupérer le lien fonction.var l = $compile(el)
Voici ce qui se passe,
$compile
parcourt l'ensemble du modèle et collecte toutes les directives qu'il reconnaît.- Toutes les directives découvertes sont compilé de manière récursive et leur
link
les fonctions sont collectées. - Ensuite, tout le
link
les fonctions sont enveloppées dans un nouveaulink
fonction et renvoyé commel
.
Enfin, nous fournissons
scope
fonction à celal
(lien) fonction qui exécute en outre les fonctions de lien encapsulées avec cescope
et leurs éléments correspondants.l(scope)
Cela ajoute le
template
en tant que nouveau nœud duDOM
et invoquecontroller
qui ajoute ses montres au portée qui est partagé avec le modèle dans DOM.
Comparant compiler contre lien contre manette :
Chaque directive est compilé une seule fois et lien la fonction est conservée pour être réutilisée.Par conséquent, s'il y a quelque chose d'applicable à toutes les instances d'une directive, il doit être exécuté dans le fichier de la directive.
compile
fonction.Maintenant, après compilation, nous avons
link
fonction qui est exécutée lors de la fixation du modèle au DOMAINE.Nous effectuons donc tout ce qui est spécifique à chaque instance de la directive.Par exemple : joindre des événements, mutation du modèle en fonction de la portée, etc.Finalement, le manette est censé être disponible pour être actif et réactif pendant que la directive travaille sur le
DOM
(après s'être attaché).Donc:(1) Après avoir configuré la vue[V] (c'est à dire.modèle) avec lien.
$scope
est notre [M] et$controller
est notre [C] dans MVC(2) Profitez du 2 voies liaison avec $portée en mettant en place des veilles.
(3)
$scope
les montres devraient être ajoutées dans le contrôleur puisque 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.(CommemyTabs
exemple dans https://docs.angularjs.org/guide/directive)(5) C'est vrai qu'on aurait pu faire tout ça dans le
link
fonctionner aussi mais c'est à propos de séparation des préoccupations.
Nous avons donc finalement ce qui suit qui s'adapte parfaitement à toutes les pièces :
Autres conseils
Pourquoi les contrôleurs sont nécessaires
La différence entre link
et controller
entre en jeu lorsque vous souhaitez imbriquer des directives dans votre DOM et exposer les fonctions API de la directive parent à celles imbriquées.
Du documents:
Meilleur entrainement:utilisez le contrôleur lorsque vous souhaitez exposer une API à d'autres directives.Sinon, utilisez le lien.
Disons que vous voulez avoir deux directives my-form
et my-text-input
et tu veux my-text-input
directive à apparaître uniquement à l'intérieur my-form
et nulle part ailleurs.
Dans ce cas, direz-vous en définissant la directive my-text-input
que c'est a besoin un contrôleur du parent
élément DOM utilisant le require
argument, comme ça: require: '^myForm'
.Maintenant, le contrôleur de l'élément parent sera injected
dans le link
fonctionner comme 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.
Pourquoi utiliser le lien
Il n'est pas vraiment nécessaire d'utiliser le link
fonction si l'on définit la controller
depuis le $scope
est disponible sur le controller
.De plus, tout en définissant à la fois link
et controller
, il faut faire attention à l'ordre d'invocation des deux (controller
est exécuté auparavant).
Cependant, conformément au Voie angulaire, la plupart des manipulations DOM et des liaisons bidirectionnelles utilisant $watchers
se fait généralement dans le link
fonctionner tandis que l'API pour les enfants et $scope
la manipulation se fait dans le controller
.Ce n'est pas une règle absolue, mais cela rendra le code plus modulaire et aidera à séparer les problèmes (le contrôleur maintiendra le directive
l'état et link
fonction maintiendra le DOM
+ reliures extérieures).
Le controller
fonction/objet représente un modèle-vue-contrôleur d'abstraction (MVC).Bien qu'il n'y ait rien de nouveau à écrire sur MVC, c'est toujours l'avantage le plus significatif d'angular :divisez les préoccupations en morceaux plus petits.Et voilà, rien de plus, donc si vous avez besoin de réagir Model
changements provenant de View
le Controller
est le droit personne pour faire ce travail.
L'histoire de link
la fonction est différente, elle vient d'un point de vue différent de celui de MVC.Et c'est vraiment essentiel, dès lors que l'on veut dépasser les frontières d'un controller/model/view
(modèle).
Commençons par les paramètres qui sont passés dans le link
fonction:
function link(scope, element, attrs) {
- portée est un objet de portée angulaire.
- élément est l'élément enveloppé dans jqLite auquel cette directive correspond.
- attributs est un objet avec les noms d'attributs normalisés et leurs valeurs correspondantes.
Mettre le link
dans le contexte, nous devons mentionner que toutes les directives passent par ces étapes de processus d'initialisation : Compiler, Lien.Un extrait de Brad Green et Shyam Seshadri livrent Angular JS:
Phase de compilation (une sœur de link, mentionnons-la ici pour y voir clair) :
Dans cette phase, Angular parcourt 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 la directive (modèle, remplacer, transcluder, etc.), et appelle la fonction de compilation s'il existe.Le résultat est une fonction de modèle compilée,
Phase de liaison:
Pour rendre la vue dynamique, Angular exécute alors une fonction de liaison pour chaque directive.Les fonctions de liaison crée généralement des auditeurs sur le DOM ou le modèle.Ces auditeurs gardent la vue et le modèle de synchronisation à tout moment.
Un bel exemple d'utilisation du link
on peut le trouver ici : Création de directives personnalisées.Voir l'exemple : Créer une directive qui manipule le DOM, qui insère une "date-heure" dans la page, actualisée toutes les secondes.
Juste un très court extrait de cela riche source ci-dessus, montrant la véritable manipulation avec DOM.Il existe une fonction liée au service $timeout, et elle est également effacée dans son destructeur appeler 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);
});
...