有一些流行的递归角度指令Q&A,它们都归结为以下解决方案之一:
第一个 问题是,除非您全面地管理手动编译过程,否则无法删除以前编译的代码。 第二种方法 的问题是……不是指令,而是失去了其强大的功能,但是更紧迫的是,不能像指令一样对它进行参数化;它只是绑定到新的控制器实例。
我一直在手动执行an angular.bootstrap或@compile()in link函数,但这给我留下了手动跟踪要删除和添加的元素的问题。
angular.bootstrap
@compile()
有没有一种好的方法来使参数化的递归模式能够管理添加/删除元素以反映运行时状态?也就是说,一棵带有添加/删除节点按钮和一些输入字段的树,其值向下传递到节点的子节点。也许是第二种方法与链接范围的组合(但是我不知道如何做到这一点)?
线程中描述的解决方案的启发,我将递归功能抽象为service。
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", ["RecursionHelper", 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) { // Use the compile function from the RecursionHelper, // And return the linking function(s) which it returns return RecursionHelper.compile(element); } }; }]);
观看此Plunker进行演示。我最喜欢此解决方案,因为:
更新:从Angular 1.5.x开始,不再需要其他技巧,但仅适用于 template ,不适用于 templateUrl