Angularjs: comprendre une directive récursive

J'ai trouvé une excellente directive sur les arbres ici. Original: http://jsfiddle.net/n8dPm/

J'ai essayé de comprendre le fonctionnement de celui-ci à travers quelques autres questions de SO, 1 , 2 . Je ne comprenais pas très bien comment les appels récursifs pour rendre la directive arborescente fonctionnent. Principalement la fonction de compilation

  1. Lorsque toutes les fonctions de compilation sont appelées?
  2. Quand est-ce que la fonction de compilation est mise en cache dans les paramètres varibale compiledContents (est-ce la fonction de liaison?), Et quand est-ce que cela ajoute? Pourquoi ne pas ajouter toujours?

 compile: function(tElement, tAttr) { var contents = tElement.contents().remove(); var compiledContents; return function(scope, iElement, iAttr) { if(!compiledContents) { compiledContents = $compile(contents); } compiledContents(scope, function(clone, scope) { iElement.append(clone); }); }; }, 

Le site Ng dispose d'une excellente documentation (certains des meilleurs à mon avis). L'aperçu des boucles de démarrage et d'exécution est très utile: http://docs.angularjs.org/guide/concepts

À un niveau élevé, lorsque Ng commence, il compile le DOM à partir duquel se trouve ng-app (traité comme une autre directive par Ng). Cela signifie qu'il passe par les éléments et les directives d'apparence et les expressions qu'il doit relier au $ rootScope (la racine de toutes les étendues qui font partie de la configuration de chaîne de patrimoine prototypique par le processus de compilation / liaison). S'il s'agit d'une directive, le processus de compilation est également effectué. Le processus de compilation prend toutes les directives Ng qu'il trouve dans le HTML et les hiérarchise en fonction de la priorité assignée ou suppose que la priorité est nulle. Lorsqu'il les a tous commandés, il exécute la fonction de compilation pour la directive qui renvoie la fonction de liaison. Dans l'exemple ci-dessus, il existe deux fonctions de lien d'émission que je vais annoter ci-dessous avec d'autres notes qui la relient à cette explication. La fonction de liaison est également donnée au code HTML qui était dans l'élément dans lequel la directive était un attribut, une classe ou un élément sous la forme de l'objet transclure.

Les fonctions de lien sont exécutées qui relient la portée et la directive avec la création d'une vue. Cela peut inclure le HTML / transclure afin qu'il puisse être ajouté là où la directive ng-transclude est dans le modèle de la directive (qui aura le même processus appliqué avec le schéma étant le transclude).

Voici donc mes notes pour la directive personnalisée légèrement corrigée ci-dessus:

 module.directive("tree", function($compile) { //Here is the Directive Definition Object being returned //which is one of the two options for creating a custom directive //http://docs.angularjs.org/guide/directive return { restrict: "E", //We are stating here the HTML in the element the directive is applied to is going to be given to //the template with a ng-transclude directive to be compiled when processing the directive transclude: true, scope: {family: '='}, template: '<ul>' + //Here we have one of the ng-transclude directives that will be give the HTML in the //element the directive is applied to '<li ng-transclude></li>' + '<li ng-repeat="child in family.children">' + //Here is another ng-transclude directive which will be given the same transclude HTML as //above instance //Notice that there is also another directive, 'tree', which is same type of directive this //template belongs to. So the directive in the template will handle the ng-transclude //applied to the div as the transclude for the recursive compile call to the tree //directive. The recursion will end when the ng-repeat above has no children to //walkthrough. In other words, when we hit a leaf. '<tree family="child"><div ng-transclude></div></tree>' + '</li>' + '</ul>', compile: function(tElement, tAttr, transclude) { //We are removing the contents/innerHTML from the element we are going to be applying the //directive to and saving it to adding it below to the $compile call as the template var contents = tElement.contents().remove(); var compiledContents; return function(scope, iElement, iAttr) { if(!compiledContents) { //Get the link function with the contents frome top level template with //the transclude compiledContents = $compile(contents, transclude); } //Call the link function to link the given scope and //a Clone Attach Function, http://docs.angularjs.org/api/ng.$compile : // "Calling the linking function returns the element of the template. // It is either the original element passed in, // or the clone of the element if the cloneAttachFn is provided." compiledContents(scope, function(clone, scope) { //Appending the cloned template to the instance element, "iElement", //on which the directive is to used. iElement.append(clone); }); }; } }; }); 

Toute la chose fonctionne: http://jsfiddle.net/DsvX6/7/