更新 Angular $interval 中的变量会导致其他函数运行



我试图尽可能地简化这个问题,所以忽略这个例子是多么毫无意义:)

我有一个显示计时器的指令。每 500 毫秒,它就会递增计数器。

.JS

.directive('testTimer', function($interval) {
    return {
        link: function(scope, el, attrs) {
            var count;
            scope.counter = 0;
            count = $interval(tick, 500);
            function tick() {
                scope.counter++;
            }
        }
    }
})

.HTML

<test-timer>{{counter}}</test-timer>

每次 tick() 运行时,我的控制器中的函数也会运行

.controller('testController', function($scope) {
    $scope.array = [
        1,2,3
    ]
    $scope.getNumber = function(num) {
        console.log('Why does this run every time tick runs?')
        return num;
    }
})

.HTML

<div ng-controller="testController">
<div ng-repeat="number in array">
    {{getNumber(number)}}
</div>

<test-timer>{{counter}}</test-timer>

我尝试在我的$interval中使用 invokeApply = false,但计数器在 DOM 中没有更新。如何防止我的指令在控制器中一遍又一遍地运行其他函数,但仍让它更新视图中的计数器?

这是一个显示问题的JS小提琴(查看控制台日志)https://jsfiddle.net/marmite/nf4c18tx/

这是

预期行为。

角度运行所谓的摘要循环来检测和传播变化。更新 {{ getNumber(number) }} 返回的值的唯一方法是评估函数调用getNumber(number),因为 Angular 不知道您是否更改了其返回值。摘要循环由$interval()调用,是标准JavaScript setInterval()的包装器。

您可以修改代码以仅使用 setInterval(),并且可以看到不再调用 getNumber(),因为没有任何东西可以触发摘要循环。

您更新的演示:https://jsfiddle.net/7Ljus149/1/

要回答您的问题:不要从函数返回数值。我不知道您的用例是什么,但我认为您不需要在{{ }}中使用函数调用。它还可能导致严重的性能问题,一般来说,避免它几乎总是更好的。

我想我已经解决了这个特定情况

我将元素传递给指令的链接函数。

link: function(scope, el, attrs) {

然后,我可以手动更新它,而不是绑定计数器的值

angular.element(el[0]).html(counter++);

最后,我告诉我的$interval不要通过将 false 作为第 4 个参数传递来调用 App。

count = $interval(tick, 500, 0, false);

链接到固定的 JSFiddle https://jsfiddle.net/marmite/9ac5j76c/

最新更新