好吧,这可能看起来有些深奥,但我正在尝试使用我编写的指令解决特定问题:https://github.com/michaelbromley/angularUtils/issues/37
这是正在发生的事情的简化版本。
这有效:
我有一个指令,通过动态添加 ng-repeat
委托(delegate)给 ng-repeat在编译阶段为元素添加属性,然后编译该元素:
myApp.directive('repeatDelegator', function($compile, $timeout) {
return {
compile: function(element, attrs){
attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
element.removeAttr('repeat-delegator'); // remove the repeat-delegator to prevent infinite recursion of compilation
var compiled = $compile(element, null);
return function(scope, element, attrs){
compiled(scope);
};
}
}
});
指令是这样调用的:
<ul>
<li repeat-delegator="item in items">{{item}}</li>
</ul>
这工作正常 - 请参阅此处的第一个示例:http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview
但是,当 repeat-delegator
放在任何其他使用包含的指令中,它不起作用。
这行不通。为什么?
这是一个基本指令,除了导致嵌入之外什么都不做:
myApp.directive('transcluder', function() {
return {
restrict: 'AE',
transclude: true,
scope: {},
template: '<div ng-transclude></div>'
};
});
所以当我们调用 repeat-delegator
在此嵌入中的指令,它失败并且没有显示任何内容:
<transcluder>
<ul>
<li repeat-delegator="meal in meals">{{meal}}</li>
</ul>
</transcluder>
第二个示例说明了这一点:http://plnkr.co/edit/oWd3rGAulsxoeSqffxMU?p=preview
目前我所知道的:
我花了几个小时逐步查看 Angular.js 源代码,因为它执行时试图找出它在嵌入内失败的原因,但我无法深入了解它。
在损坏的(嵌入的)版本中,当我看到正在编译的 ngRepeat 时,$scope 似乎是正确的(它是主 Controller $scope 的子 $scope,因为嵌入导致新的子 $scope被创建)。您可以在控制台中写入“scope.items”并查看项目列表。
我猜是这样的事情正在发生:
- transcluder指令最先被编译,因为它在DOM树中的位置更高,所以最先遇到。
- 嵌入导致指令的子节点从 DOM 中移除并克隆到
$template
中var,用于稍后插入回 DOM。 - 也许这会导致
ng-repeat
针对<li>..</li>
的克隆 进行编译节点,实际上永远不会附加回 DOM?
虽然我不确定。这是一个非常棘手的问题,我们将不胜感激任何帮助!
最佳答案
好吧,在花了一天时间在开发工具中破解 Angular.js 源代码之后,我弄清楚了这里出了什么问题,我上面的猜测基本上是正确的。
问题在于 repeat-delegator
指令会针对分离的克隆进行编译,因此有效地 ng-repeated 元素将附加到丢失的 DOM 片段,而该片段永远不会附加回页面正文。
解决方案相当简单:将 repeat-delegator 委托(delegate)的 ng-repeat 的编译移动到链接函数中(而不是在编译阶段,它最初所在的位置)。
这样做意味着当 ng-repeat 被编译时,它是针对正确的 DOM 节点完成的,该节点现在安全地附加到 transcluded 指令下方的 DOM。
myApp.directive('repeatDelegator', function($compile, $timeout) {
return {
compile: function(element, attrs){
attrs.$set('ngRepeat', attrs.repeatDelegator); //Add ng-repeat to the dom
element.removeAttr(attrs.$attr.repeatDelegator); // remove the repeat-delegator to prevent infinite recursion of compilation
return function(scope, element, attrs){
var compiled = $compile(element);
compiled(scope);
};
}
}
});
关于javascript - AngularJS:为什么这个委托(delegate)的 ng-repeat 在嵌入中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25424491/