我已经构建了一个简单的指令,它添加了一个基于javascript的加载动画。它使用window.setInterval()
循环运行。这很好用,但是在加载完成后,我使用ngSwitch
来交换我的内容,这会从页面中删除包含加载指令属性的元素。
理想情况下,我想观察此更改并清除我的间隔,以便动画计算不会在后台运行。我试过看一个自定义函数来评估页面上元素的存在。我知道该函数可以检测到这一点,但似乎时间问题 - 也就是说,据我所知,$watch
本身在指令属性的元素离开页面时被清除。因此,我的$watch
'ed表达式永远不会检测到更改,并且永远不会调用其清除动画间隔函数的回调。
是否有建议的模式来处理这种情况?
我的模板中的相关摘录:
<div ng-switch on="dataStatus">
<div ng-switch-when="loading">
<div loading-spinner></div>
</div>
<div ng-switch-when="haveData">
<!-- data dependent on content we were loading -->
</div>
</div>
我的指令的简化版本:
myModule.directive('loadingSpinner', function () {
var updateMySweetAnimation = function (element) { /* ... */ };
return {
link: function (scope, iElement, iAttrs) {
var spinner = window.setInterval(function () {
updateMySweetAnimation(iElement);
}, 100);
scope.$watch(function () {
return $(document).find(iElement).length;
}, function (present) {
if (!present) {
clearInterval(spinner);
}
});
}
};
});
答案 0 :(得分:2)
当ng-switch
从页面中清除元素时,应该发生两件事:
为ng-switch-when
创建的作用域,即指令所在的元素,将被销毁。这会导致您的$watch
被杀,并在您可以使用$destroy
观看的范围内生成scope.$on('$destroy', ...)
个事件。
该元素已从DOM中删除。这会生成一个单独的销毁事件,您可以使用iElement.on('$destroy', ...)
观看。
它们应按此顺序发生,查看最新的稳定版本(1.0.8 - https://github.com/angular/angular.js/blob/v1.0.8/src/ng/directive/ngSwitch.js),因此当从DOM中删除元素时,您的范围以及您的监视应始终处于死亡状态。
您可以通过观察定义ng-switch
的外部范围来避免此问题。或者您可以观看dataStatus
,与ng-switch
中的条件相同,而不是查看ng-switch
看到您的情况发生变化的结果。
这两种方法都可能有效,但实际上您需要做的就是实际上正常模式,只需观察其中一个$destroy
事件并清理其中的所有内容。由于区间感觉与视图的相关性高于模型,我会使用DOM事件并将$watch
替换为
iElement.on('$destroy', function(){
clearInterval(spinner);
});