我正在将AngularJS用于某个应用程序,并且在将更改推送到视图时遇到了一些问题。
用例
当我对视图/数据进行重大更新(xhr请求,恢复状态和批次)时,我用一个加载器gif向用户发送了它。我使用一个绑定到img标签的标志(使用ngClass),因此在设置标志时会显示加载程序gif。该标志也用作锁(不是以线程安全的方式,但对于手头的任务来说足够好)。我在启动一个进程时获得了锁(设置标志),并在所有xhr调用的最后一个promise($ q)被解析后释放它。
问题
当我使用HTML5历史记录API恢复数据并从服务器加载数据时(在重新加载,向前或向后),视图可能需要花费大量时间来反映对模型所做的更改。由于我只依赖于http请求的承诺,我的加载器gif在视图(可见)更新之前被隐藏。有没有办法检测用户何时可以看到更改而不是观察模型更改?这可能不再是Angular问题,而是一般的JS问题。
时间线
(1)设置标志 - >
(2)执行xhr /模型更改 - >
(3)释放锁定 - >
(4)AngularJS完成申请 - >
(5)可见变化
问题主要在于步骤4和步骤5(也是第3步和第4步,但这实际上并不明显)。
示例
作为用户,我可以清楚地看到正在生成的表行,但表格单元格仍为空。几十毫秒后,会显示值。我不确定这是否是默认的Angular行为,或者我的浏览器是否有足够的麻烦来快速呈现对HTML的更改。
我的想法
我猜这个问题与浏览器更新视口的方式交织在一起。我还没有真正深入研究,但在我看来,Angular实际上已应用了这些更改,但它们尚未被浏览器呈现。使用指向$ last标志的主数据表的指令,我可以检测到ng-repeat完成和视图呈现之间的相当大的延迟。这可能是因为浏览器的细节太多了,但也许其他人对此有一些想法要分享:)
答案 0 :(得分:2)
你可以拥有最低优先级的指令......例如-1并使用该指令显示或隐藏spinner / gif元素
作为具有最低优先级的指令,这将在视图更新中最后执行。所以show-spinner在这个指令的一部分可能是假的,因此只有在渲染所有更改后,spinner才会隐藏...
答案 1 :(得分:2)
这可能有点hackish,但我有一种情况,外部lib必须将事件监听器附加到ngRepeat
生成的元素。显然,当模型观察者解雇时,元素还没有出现,所以我所做的是ngRepeat
元素上的自定义指令,它将监视ngRepeat
的{{1}}属性然后$last
1}}需要回调。这是个主意:
$evalAsync
考虑到这一点,您可以隐藏加载程序图像,而不是在释放锁定时,但是当某个事件(比如.directive('onRepeatFinish', function() {
return {
restrict: 'A',
link: function(scope, element, attributes) {
if (scope.$last === true) {
scope.$evalAsync(attributes.onRepeatFinish);
}
}
};
})
)由此指令发送时。
模板:
renderComplete
$ rootScope中的处理程序:
<div ng-repeat="record in data" on-repeat-finish="$emit('renderComplete')"></div>