Angularjs: entendendo uma diretiva recursiva

Eu encontrei uma ótima diretiva de tree aqui. Original: http://jsfiddle.net/n8dPm/

Eu tenho tentado entender o funcionamento do mesmo através de outras questões do SO, 1 , 2 . Eu não conseguia entender como as chamadas recursivas para processar a diretiva de tree funcionam. Principalmente a function de compilation

  1. Quando toda a function de compilation é chamada?
  2. Quando é a function de compilation $ armazenada em cache no compibatc compiledContents (esta é a function de link?), E quando é anexada? Por que não é append sempre?

 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); }); }; }, 

O site do Ng tem uma ótima documentação (algumas das melhores que existem na minha opinião). A visão geral dos loops de boot e tempo de execução é muito útil: http://docs.angularjs.org/guide/concepts

Em um nível alto, quando o Ng começa, ele compila o DOM começando onde o ng-app está localizado (tratado como apenas outra diretiva por Ng). Isso significa que ele percorre os elementos e procura diretivas e expressões necessárias para vincular-se ao $ rootScope (a raiz de todos os escopos que fazem parte da configuração da cadeia de inheritance prototípica pelo processo de compilation / vinculação). Se for uma diretiva, o processo de compilation também é feito nela. O processo de compilation pega todas as diretivas Ng que ele encontra no HTML e as prioriza com base na prioridade atribuída ou assume que a prioridade é zero. Quando todos eles ordenam, executa a function de compilation para a diretiva que retorna a function de link. No exemplo acima, há duas funções show link que anoto abaixo, junto com outras notas que ligam a essa explicação. a function de link também recebe o HTML que estava no elemento em que a diretiva era um atributo, uma class ou um elemento na forma do object transclude.

As funções de binding são executadas, ligando o escopo e a diretiva, além de produzir uma visão. Isso pode include o HTML / transclude, de modo que possa ser adicionado onde a diretiva ng-transclude esteja no modelo da diretiva (que terá o mesmo processo aplicado a ele, com seu modelo sendo o transclude).

Então, aqui estão minhas annotations para a diretiva personalizada ligeiramente corrigida acima:

 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: '
    ' + //Here we have one of the ng-transclude directives that will be give the HTML in the //element the directive is applied to '
  • ' + '
  • ' + //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. '
    ' + '
  • ' + '
', 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); }); }; } }; });

Coisa toda trabalhando: http://jsfiddle.net/DsvX6/7/