有几个流行的递归 Angular Directive(指令)问答,它们都归结为以下解决方案之一:
- 根据运行时范围状态手动增量“编译”HTML
- 根本不使用指令,而是使用引用自身的 <script> 模板
第一个的问题是,除非您全面管理手动编译过程,否则无法删除以前编译的代码。 第二种方法的问题是......不是指令并且错过了它强大的功能,但更紧迫的是,它不能像指令一样被参数化;它只是绑定(bind)到一个新的 Controller 实例。
我一直在尝试在链接函数中手动执行 angular.bootstrap
或 @compile()
,但这给我留下了手动跟踪的问题要删除和添加的元素。
有没有一种好方法可以使用参数化的递归模式来管理添加/删除元素以反射(reflect)运行时状态?也就是说,具有添加/删除节点按钮和一些输入字段的树,其值向下传递到节点的子节点。也许是第二种方法与链式作用域的结合(但我不知道该怎么做)?
最佳答案
受@dnc253 提到的线程中描述的解决方案的启发,我抽象了递归功能into a 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演示。 我最喜欢这个解决方案,因为:
- 您不需要使您的 html 变得不那么干净的特殊指令。
- 递归逻辑被抽象到 RecursionHelper 服务中,因此您可以保持指令简洁。
更新: 从 Angular 1.5.x 开始,不再需要任何技巧,但仅适用于 template,不适用于 templateUrl
关于javascript - Angular 指令中的递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14430655/