我已经定义了以下指令,该指令包装了UI Bootstrap提供的pagination
指令
angular.module('my-module')
.directive('myPagination', ['$filter', '$window', function ($filter, $window) {
return {
restrict: 'EA',
scope: {
itemsPerPage: '=',
totalItems: '=',
page: '='
},
link: function (scope, element, attrs) {
scope.hiddenElement = true;
var totalMargin = 200, widthByElement = 41;
scope.getWindowDimensions = function () {
return {
'w': element.width()
};
};
scope.$watch(scope.getWindowDimensions, function (newWidth, oldWidth) {
// calculate how many page buttons fit in the pagination horizontal bar
scope.maxSize = parseInt($filter('number')((newWidth.w - totalMargin) / widthByElement, 0));
}, true);
angular.element($window).bind('resize', function () {
// "$digest already in progress" thrown by the following line
scope.$apply();
});
},
template: '<div class="text-center paginationSelfCare" ng-show="totalItems > itemsPerPage">' +
'<pagination ng-show="totalItems/itemsPerPage <= maxSize" total-items="totalItems" items-per-page="itemsPerPage" ng-model="page" max-size="maxSize" class="pagination pagination-sm" ></pagination>' +
'<pagination ng-show="totalItems/itemsPerPage > maxSize" total-items="totalItems" boundary-links="true" direction-links="true" previous-text="<" next-text=">" first-text="<<" last-text=">>" items-per-page="itemsPerPage" ng-model="page" max-size="maxSize" class="pagination pagination-sm" ></pagination>' +
'</div>'
};
}]);
如果此指令在一个浏览器选项卡(A)中运行,并且我切换到另一个选项卡(B),那么当我切换回A时,我在浏览器控制台中看到以下错误:
错误:[$ rootScope:inprog] $ digest已在进行中 http://errors.angularjs.org/1.4.4/ $ rootScope / inprog?P0 =%24digest minErr /&LT; @ http://127.0.0.1:9000/bower_components/angular/angular.js:68:12 beginPhase @ http://127.0.0.1:9000/bower_components/angular/angular.js:16273:1 $ RootScopeProvider / $这gethttp://127.0.0.1:9000 / bower_components /角度/ angular.js:16014:11 。链接/&LT; @ http://127.0.0.1:9000/scripts/directives/pagination.js:30:11
pagination.js
的第30行是标有上述评论的行
scope.$apply();
在致电scope.$apply();
之前,有什么我可以检查以避免此问题吗?我正在运行Angular版本1.4.4
答案 0 :(得分:4)
您可以尝试$socpe.$applyAsync()
而不是$scope.$apply()
,这绝不会与当前正在运行的摘要周期发生冲突。
$apply
上的{p> $scope
直接尝试运行摘要周期。它不会检查是否有任何摘要周期,并且您运行摘要循环,它会抛出$digest already in progress
。
虽然您可以使用包装代码$timeout
功能来解决此问题,但我更倾向于使用$applyAsync
scope
方法。
$timeout
确实运行digest
周期,但在运行之前,它会检查是否正在进行任何摘要,然后将此digest
周期调用运行到队列中并在运行后运行它消化周期完成。
$applyAsync
是运行摘要周期的性能改进版本,当您运行此方法时,它首先检查是否正在运行任何摘要周期。如果发现任何正在运行的摘要周期,它会将该块放在该摘要周期中(这意味着您减少了一个摘要周期)。
答案 1 :(得分:0)
你的手表很奇怪。这是通常的方式:
angular.element($window).bind('resize', function () {
// There are a lot of resize events, we do not need to change smth on each
// Once per some time is ok.
if (attrs.lastResize) {
$timeout.cancel(attrs.lastResize)
}
attrs.lastResize = $timeout(function() {
// actual code like
// like scope.maxSize = calc();
}, 75)
});
你不需要在这里申请,因为你有$ timeout。