导致无限摘要循环的指令

Directive causing infinite digest loop

以下指令导致无限摘要循环,我不确定原因。关于如何重新编写代码的任何想法?

谢谢!

  .directive('fitHeight', ['$window', '$timeout', '$location', function ($window, $timeout, $location) {
return {
  restrict: 'A',
  scope: true,
  link: function (scope, element, attr) {
    scope.docHeight = $(document).height();
    var setHeight = function (newVal) {
      var diff = $('header').height();
      if ($('body').hasClass('layout-horizontal')) diff += 112;
      if ((newVal-diff)>element.outerHeight()) {
        element.css('min-height', (newVal-diff)+'px');
      } else {
        element.css('min-height', $(window).height()-diff);
      }
    };
    scope.$watch('docHeight', function (newVal, oldVal) {
      setHeight(newVal);
    });
    $(window).on('resize', function () {
      setHeight($(document).height());
    });
    var resetHeight = function () {
        scope.docHeight = $(document).height();
        $timeout(resetHeight, 1000);
      }
    $timeout(resetHeight , 1000);
  }
};

你有一个无限循环调用 resetHeight 函数内部的 resetHeight 函数。无限 $digest 循环是该无限循环的副作用。

您的 $timeout(resetHeight, 1000) 导致了 Infinite $digest loop。这是因为方法 resetHeight 正在改变变量 $scope.docHeight 并开始另一个 $timeout 循环,$timeout 触发 $scope.$apply()。在内部 Angular 监视可能看起来或实际上是什么,并且无穷无尽 $digest loop,如果发现这种情况,则会抛出异常。

我不得不做一些类似于你正在做的事情,我不会在 Window Resize 事件上做 Debouncing 逻辑。这是因为在调整 window 的大小时会触发该事件。您将需要 throttle 处理程序调用,这样您就不会 $digest loops.

在我下面的示例中,我将 Lodash 用于我的去抖动逻辑。

http://plnkr.co/edit/vUHcgpveDvijGE6l1LXy?p=preview

            angular.module('myApp', [])
                .directive('fitHeight', ['$window', '$timeout', '$location', function ($window, $timeout, $location) {
                    return {
                        restrict: 'A',
                        scope: true,
                        link: function (scope, element, attr) {
                            function setHeight(newVal) {
                                var diff = $('header').height();

                                if ($('body').hasClass('layout-horizontal')) {
                                    diff += 112;
                                }

                                if ((newVal - diff) > element.outerHeight()) {
                                    element.css('min-height', (newVal - diff) + 'px');
                                    console.log('if');
                                } else {
                                    element.css('min-height', $(window).height() - diff);
                                    console.log('else');
                                }
                            }

                            setHeight($(document).height());

                            var docHeight = $(document).height();
                            var heightCheck = function() {
                                if (docHeight != $(document).height()) {
                                    docHeight = $(document).height();

                                    setHeight(docHeight);
                                }
                            };

                            var lazyHeightCheck = _.debounce(heightCheck, 200);
                            $(window).on('resize', lazyHeightCheck);

                            element.on('$destroy', function() {
                                $(window).off('resize', lazyHeightCheck);
                            });
                        }
                    }
                }]);