最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angularjs: understanding a recursive directive - Stack Overflow

programmeradmin1浏览0评论

I found a great tree directive here. Original: /

I have been trying to understand the functioning of it through couple of other SO questions, 1,2 . I couldn't quite understand how the recursive calls to render the tree directive work. Mainly the compile function

  1. When all the compile function called?
  2. When is the $compile function cached in the varibale compiledContents (is this the link function?), and when is it appends? Why it is not append always?

--

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

I found a great tree directive here. Original: http://jsfiddle.net/n8dPm/

I have been trying to understand the functioning of it through couple of other SO questions, 1,2 . I couldn't quite understand how the recursive calls to render the tree directive work. Mainly the compile function

  1. When all the compile function called?
  2. When is the $compile function cached in the varibale compiledContents (is this the link function?), and when is it appends? Why it is not append always?

--

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); 
                });
            };
        },
Share Improve this question edited May 23, 2017 at 11:53 CommunityBot 11 silver badge asked Oct 1, 2013 at 20:44 bsrbsr 58.7k88 gold badges217 silver badges321 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 32

The Ng site has some great documentation (some of the best around in my opinion). The overview of the Startup and Runtime loops are very helpful: http://docs.angularjs.org/guide/concepts

At a high level, when Ng first starts it compiles the DOM starting at where ng-app is located (treated like just another directive by Ng). This means it goes through the elements and looks directives and expressions it needs to link up to the $rootScope (the root of all scopes that are part of the prototypical inheritance chain setup by the compiling/linking process). If it is a directive, the compile process is done on it as well. The compiling process takes all of the Ng directives it finds in the HTML and prioritizes them based on there assigned priority or assumes the priority is zero. When it has them all ordered it executes the compile function for the directive which returns the link function. In the above example there are two show link functions which I will annotate below along with other notes linking it to this explanation. the link function also is given the HTML that was in the element the directive was a attribute, class, or element on in the form of the transclude object.

The link functions are executed which links the scope and the directive along with producing a view. This may include the HTML/transclude so it can be added where the directive ng-transclude is in the template of the directive (which will have the same process applied to it with it's template being the transclude).

So here are my notes for the slightly corrected custom directive above:

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

Whole thing working: http://jsfiddle.net/DsvX6/7/

发布评论

评论列表(0)

  1. 暂无评论