AngularJS中递归嵌套指令

3
我尝试在AngularJS中实现递归嵌套指令。
我简单地创建了一个<tree-dir>指令并获得了jsFiddle
在我的tree_item_renderer.html模板中,如果我将ng-include替换为<tree-dir>,当编译时,Angular会进入无限循环(如果您尝试它,它将使您的浏览器变慢或停止)。
来源:this question 关于angular中递归树的问题。

这个答案似乎很有帮助:https://dev59.com/BWct5IYBdhLWcg3wvf_K#19065910 - arthur.sw
可能是重复的问题:是否可以使用Angular制作树形视图? - JG in SD
https://github.com/dotJEM/angular-tree - Jens
2个回答

4
这个答案解释并解决了所有问题,以下是最重要的部分:
当制作树形视图时,最好的解决方案是使用递归指令。然而,当你制作这样一个指令时,你会发现AngularJS进入了无限循环。
解决方法是让指令在编译事件期间删除元素,并在链接事件中手动编译和添加它们。
我在这个主题中发现了这个功能,并将其抽象成一个服务
module.factory('RecursionHelper', ['$compile', function($compile){
    return {
        /**
         * Manually compiles the element, fixing the recursion loop.
         * @param element
         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
         * @returns An object containing the linking functions.
         */
        compile: function(element, link){
            // Normalize the link parameter
            if(angular.isFunction(link)){
                link = { post: link };
            }

            // Break the recursion loop by removing the contents
            var contents = element.contents().remove();
            var compiledContents;
            return {
                pre: (link && link.pre) ? link.pre : null,
                /**
                 * Compiles and re-adds the contents
                 */
                post: function(scope, element){
                    // Compile the contents
                    if(!compiledContents){
                        compiledContents = $compile(contents);
                    }
                    // Re-add the compiled contents to the element
                    compiledContents(scope, function(clone){
                        element.append(clone);
                    });

                    // Call the post-linking function, if any
                    if(link && link.post){
                        link.post.apply(null, arguments);
                    }
                }
            };
        }
    };
}]);

使用此服务,您可以轻松地创建树指令(或其他递归指令)。以下是一个树指令的示例:

module.directive("tree", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {family: '='},
        template: 
            '<p>{{ family.name }}</p>'+
            '<ul>' + 
                '<li ng-repeat="child in family.children">' + 
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(element) {
            return RecursionHelper.compile(element);
        }
    };
});

查看此Plunker以查看演示。我认为这个解决方案最好的原因是:

  1. 您不需要特殊指令,这使得您的HTML更加简洁。
  2. 递归逻辑被抽象成RecurisionHelper服务,因此您可以保持指令的干净。

请查看http://benfoster.io/blog/angularjs-recursive-templates,我认为你所建议的任何内容都是不必要的。构建嵌套指令非常容易。 - orange
那个解决方案完美地运作了,谢谢!我真的很喜欢你所需要做的非常少的方式来使用它 - 只需提供编译功能 - 尽管你也应该传递链接功能(编译方法有好的注释,所以很容易弄清楚)。干得好。 :) - Allan Nienhuis

0

我认为你需要通过作用域变量将子节点传递给子指令。在你的例子中,根节点总是被取出并反复渲染。

或者可以参考this的例子。模板逻辑完全能够渲染嵌套指令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接