【问题标题】:How can you detect when HTML rendering is completed in AngularJS如何在 AngularJS 中检测 HTML 渲染何时完成
【发布时间】:2017-10-11 15:01:01
【问题描述】:

我已经对这个主题进行了广泛的研究,但无论我做什么,我都觉得实现这个目标非常困难。

我想在 AngularJS Web 应用程序中完全呈现所有元素后执行代码。我想我找到了建议使用路由器和视图的解决方案,但我无法在我的情况下使用它,因为它似乎需要某些配置。

当您拥有ng-repeat 和许多嵌套的directives 时,它们将使用ng-if 根据各种条件生成 HTML/内容,我注意到即使在触发文档就绪事件或查看内容之后,HTML 渲染也会继续加载即触发$viewContentLoaded事件。

我最接近的想法是在给定directive 的元素的子元素的长度上使用$watch。每次执行$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);
        }
    }
});

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

塔雷克

【问题讨论】:

    标签: angularjs html rendering loading


    【解决方案1】:

    我开发了以下指令,在 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 让您了解它的工作原理。

    塔雷克

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 谢谢!我会试试看。但是,我记得任何以 $$ 开头的 AngularJS API 都不能 100% 安全使用,对吗?
      • 抱歉,您的解决方案对我不起作用。请参阅上面的解决方案,以便您更好地了解我要做什么。谢谢!
      猜你喜欢
      • 2014-01-26
      • 2022-11-02
      • 1970-01-01
      • 2021-11-26
      • 2015-12-14
      • 2023-03-17
      • 2021-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多