Selon la documentation, un template
peut être une fonction qui prend deux paramètres, un element
et attributes
et retourne une valeur de chaîne représentant le modèle. Il remplace l'élément courant par le contenu du HTML. Le processus de remplacement migre tous les attributs et classes de l'ancien élément vers le nouveau.
La fonction compile
traite de la transformation du modèle DOM. Il prend trois paramètres, une fonction element
, attributes
et transclude
. Le paramètre transclude
est obsolète. Il renvoie une fonction link
.
Il semble que les fonctions template
et compile
sont très similaires et peuvent réaliser la même chose. La fonction template
définit un modèle et la fonction compile
modifie le modèle DOM. Cependant, cela peut être fait dans la fonction template
elle-même. Je ne vois pas pourquoi modifier le modèle DOM en dehors de la fonction template
. Et vice-versa si le DOM peut être modifié dans la fonction compile
, alors quel est le besoin d'une fonction template
?
La fonction de compilation peut être utilisée pour modifier le DOM avant que la fonction de modèle résultante soit liée à la portée.
Prenons l'exemple suivant:
<div my-directive></div>
Vous pouvez utiliser la fonction de compilation pour modifier le modèle DOM comme ceci:
app.directive('myDirective', function(){
return {
// Compile function acts on template DOM
// This happens before it is bound to the scope, so that is why no scope
// is injected
compile: function(tElem, tAttrs){
// This will change the markup before it is passed to the link function
// and the "another-directive" directive will also be processed by Angular
tElem.append('<div another-directive></div>');
// Link function acts on instance, not on template and is passed the scope
// to generate a dynamic view
return function(scope, iElem, iAttrs){
// When trying to add the same markup here, Angular will no longer
// process the "another-directive" directive since the compilation is
// already done and we're merely linking with the scope here
iElem.append('<div another-directive></div>');
}
}
}
});
Vous pouvez donc utiliser la fonction compile
pour changer le modèle DOM en ce que vous voulez si votre directive l'exige.
Dans la plupart des cas, tElem
et iElem
seront le même élément DOM, mais parfois cela peut être différent si une directive clone le modèle pour en tamponner plusieurs copies (cf. ngRepeat
) .
Dans les coulisses, Angular utilise un processus de rendu bidirectionnel (compilation + lien) pour supprimer les copies d'un morceau compilé de DOM, pour empêcher Angular de avoir à traiter (= analyser les directives) le même DOM maintes et maintes fois pour chaque instance au cas où la directive éradique plusieurs clones résultant en de bien meilleures performances.
J'espère que ça t'as aidé!
AJOUTÉ APRÈS COMMENTAIRE:
La différence entre une fonction template
et compile
:
{
template: function(tElem, tAttrs){
// Generate string content that will be used by the template
// function to replace the innerHTML with or replace the
// complete markup with in case of 'replace:true'
return 'string to use as template';
}
}
{
compile: function(tElem, tAttrs){
// Manipulate DOM of the element yourself
// and return linking function
return linkFn(){};
}
}
La fonction de modèle est appelée avant l'appel de la fonction de compilation.
Bien qu'ils puissent effectuer des tâches presque identiques et partager la même "signature", la principale différence est que la valeur de retour de la fonction de modèle remplacera le contenu de la directive (ou le balisage de directive complet si replace: true
), alors qu'une fonction de compilation devrait modifier le DOM par programme et renvoyer une fonction de lien (ou un objet avec des fonctions de lien avant et après).
En ce sens, vous pouvez considérer la fonction de modèle comme une sorte de fonction de commodité pour ne pas avoir à utiliser la fonction de compilation si vous avez simplement besoin de remplacer le contenu par une valeur de chaîne.
J'espère que ça t'as aidé!
L'une des meilleures utilisations de la fonction de modèle est de générer un modèle de manière conditionnelle. Cela vous permet d'automatiser la création d'un modèle basé sur un attribut ou toute autre condition.
J'ai vu des modèles très volumineux qui utilisent ng-if
pour masquer des sections du modèle. Mais au lieu de tout placer dans le modèle et d'utiliser ng-if
, ce qui peut entraîner une liaison excessive, vous pouvez supprimer des sections du DOM de la sortie de la fonction de modèle qui ne seront jamais utilisées.
Supposons que vous ayez une directive qui inclura une sous-directive item-first
ou item-second
. Et la sous-directive ne changera jamais pendant la durée de vie de la directive externe. Vous pouvez ajuster la sortie du modèle avant d'appeler la fonction de compilation.
<my-item data-type="first"></my-item>
<my-item data-type="second"></my-item>
Et la chaîne de modèle pour ceux-ci serait:
<div>
<item-first></item-first>
</div>
et
<div>
<item-second></item-second>
</div>
Je suis d'accord qu'il s'agit d'une simplification extrême, mais j'ai des directives très compliquées et la directive externe doit afficher l'une des 20 directives internes différentes, basées sur un type. Au lieu d'utiliser transclude, je peux définir le type sur la directive externe et demander à la fonction de modèle de générer le modèle correct avec la directive interne correcte.
Cette chaîne de modèle correctement formatée est ensuite transmise à la fonction de compilation, etc.