我构建了一个简单的指令,它添加了基于javascript的加载动画。它以window.setInterval()
回路运行。这很好用,但是当加载完成后,我使用 ngSwitch
交换我的内容,这会从页面中删除包含 load 指令属性的元素。
理想情况下,我想观察此更改并清除间隔,以便动画计算不会仍在后台运行。我尝试观察一个自定义函数,该函数评估页面上元素的存在。我知道该函数可以检测这一点,但似乎时间是一个问题——也就是说,据我所知,当指令属性的元素离开页面时,$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);
}
});
}
};
});
当元素被ng-switch
从页面中清除时,应该发生两件事:
-
为
ng-switch-when
创建的作用域,即带有指令的元素,将被销毁。这会杀死您的$watch
,并在您可以使用scope.$on('$destroy', ...)
观看的范围内生成一个$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);
});