如何在AngularJS

时间:2017-10-11 15:01:01

标签: html angularjs html5 rendering loading

我已经就这个问题进行了广泛的研究,但不管我做了什么,我发现实现这个目标非常困难。

我想在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);
        }
    }
});

我会尝试实施上述方法,如果您有反馈,请告诉我。

塔雷克

2 个答案:

答案 0 :(得分:0)

您可以在摘要周期完成后使用$$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
});

答案 1 :(得分:0)

我开发了以下指令,该指令在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让您了解它是如何运作的。

塔雷克