angularjs的ngRepeat指令不会触发列表中其他项的digest

angularjs ngRepeat directive to not trigger digest for other items in the list

本文关键字:列表 其他 digest ngRepeat 指令 angularjs      更新时间:2023-09-26

似乎ngRepeat在更改其中一项后会触发任何列表项上的手表。我已经在使用track by了,所以这似乎没有帮助。

这是我的模板:

div(ng-repeat="poll in polls track by poll._id")
  poll(poll="poll")
.poll
  .title(ng-if="!poll.closed") {{poll.title}}
  .btn(ng-click="poll.closed = true") Change poll
  {{someExpensiveComputation(poll._id)}}
javascript:

.directive('poll', function($rootScope, $modal) {
  return {
    replace: false,
    restrict: 'E',
    scope: {
      poll: '='
    },
    templateUrl: '/tmpl/poll',
    link: function($scope, elem, attrs) {
      $scope.someExpensiveComputation = function (id) { ... }
    }
  }
});

似乎无论何时更改投票项,someexpensivcompute函数都会为所有投票运行,每次运行3次。我怎么才能让它不那样呢?它应该只会触发该指令的监视者。我认为这应该是可能的。

谢谢。

所有watch-表达式在每次$digest循环中被处理(求值)多次。
因此,保持watch-表达式尽可能简单(就计算复杂性而言)是一个很好的做法。

(顺便说一句,在视图中使用{{...}}会创建一个手表)

如果someExpensiveComputation()在计算上很昂贵,您不希望每次都计算它,而只希望在可能产生不同结果时才计算它。这取决于函数的实现,但是假设它的结果只依赖于每个轮询的属性,那么您可以观察轮询,并在它被更改时调用昂贵的函数:

.poll
...
{{expensivelyComputedValue}}
.directive('poll', function($rootScope, $modal) {
    return {
        ...
        link: function(scope, elem, attrs) {
            function someExpensiveComputation(id) { ... }
            scope.expensivelyComputedValue = someExpensiveComputation(scope.poll.id);
            scope.$watch('poll', function (newValue, oldValue) {
                if (newValue === oldValue) { return; }
                scope.expensivelyComputedValue = someExpensiveComputation(scope.poll.id);
            }, true);
        }
    }
});
当然,如果昂贵的计算结果仅取决于poll的特定属性(而不是整个对象),则只监视这个属性就足够了,从而使watch-表达式更加"轻量级"。例如:
scope.$watch('poll.closed', function (...) {...});