如何在AngularJS中完成HTML渲染的时候检测到
问题描述:
我对这个主题做了大量的研究,但无论我做了什么,我都觉得实现这个目标非常困难。如何在AngularJS中完成HTML渲染的时候检测到
我想在AngularJS Web应用程序中完全呈现所有元素时执行代码。我想我找到了解决方案,建议使用路由器和视图,但我无法对我的情况做出这项工作,因为它似乎需要特定的配置。
当你有ng-repeat
和大量的嵌套directives
将基于使用ng-if
各种条件生成HTML /内容,我注意到,HTML渲染继续即使文档准备事件被解雇或视图内容已经被加载即$viewContentLoaded
事件触发。
我最近的想法是使用$watch
在给定directive
的元素的子元素的长度。每次执行$watch
时,都会增加计数器renderCount
。然后,在另一个计时器事件中,检查计数器renderCount
过去是否改变了3-5秒,那么我们可以假设渲染已完成。
观看了孩子,并检查是否没有更多的渲染正在发生,可能的代码如下:
app.directive('whenRenderingDone', function($interval, $parse){
return {
link: function (scope, el, attrs) {
var renderingCount = 0;
function watchForChildren() {
scope.$watch(function(){
return $(':input', el).length;
}, function(newVal, oldVal){
if (newVal) {
renderingCount++;
}
})
}
watchForChildren();
//Check counter every 3 seconds, if no change since last time, this means rendering is done.
var checkRenderingDone = $interval(function(){
var lastCount = lastCount || -1;
if (lastCount === renderingCount) {
var func = $parse(attrs.whenRenderingDone);
$interval.cancel(checkRenderingDone);
func(scope);
}
lastCount = renderingCount || -1;
}, 3000);
}
}
});
我会尝试实施上述方法,如果您有反馈意见,请让我知道。
塔里克
答
您可以使用$$postDigest
消化周期完成之后运行的代码。你可以阅读更多有关范围的生命周期here
// Some $apply action here or simply entering the digest cycle
scope.$apply(function() { ... });
...
scope.$$postDigest(function() {
// Run any code in here that will run after all the watches complete
// in the digest cycle. Which means it runs once after all the
// watches manipulate the DOM and before the browser renders
});
答
我制定了以下指令,它是Chrome和IE11下正常工作:
app.directive('whenRenderingDone', function($timeout, $parse){
return {
link: function (scope, el, attrs) {
var lastCount;
var lastTimer = 5000; // Initial timeout
//Check counter every few seconds, if no change since last time, this means rendering is done.
var checkRenderingDone = function(){
var mainPromiseResolved = scope.mainPromiseResolved;
lastCount = lastCount || -1;
if (lastCount === el.find('*').length && mainPromiseResolved) {
console.log('Rendering done, lastCount = %i', lastCount);
var func = $parse(attrs.whenRenderingDone);
func(scope);
} else {
lastCount = el.find('*').length;
console.log('mainPromiseResolved = %s, lastCount %i', mainPromiseResolved, lastCount)
console.log('Rendering not yet done. Check again after %i seconds.', lastTimer/1000.00);
stopCheckRendering = $timeout(checkRenderingDone, lastTimer);
lastTimer = lastTimer - 1000;
if (lastTimer <= 0) {
lastTimer = 1000;
}
return stopCheckRendering;
}
}
var stopCheckRendering;
stopCheckRendering = checkRenderingDone();
el.on('$destroy', function() {
if (stopCheckRendering) {
$timeout.cancel(stopCheckRendering);
}
});
}
}
});
我希望这将是对你有所帮助,如果你有任何意见可以改进,请告诉我。 See this给你一个关于它是如何工作的想法。
Tarek
谢谢!我会试试看。但是,我记得任何以'$$'开头的AngularJS API都不是100%安全的,这是否正确? – tarekahf
抱歉,您的解决方案对我无效。看到我上面的解决方案,以便您能更好地了解我正在尝试做什么。谢谢! – tarekahf