2016-02-11 25 views
3

我試圖簡化這個問題,儘可能讓忽略這個例子是如何毫無意義的是:)

我有一個顯示計時器的指令。每500ms它會增加計數器。

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> 

每次蜱()運行,在我的控制器功能也跑

.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> 

我試過在我的$間隔中使用invokeApply = false,但是然後計數器不在DOM中更新。我該如何防止我的指令反覆地在控制器中運行其他函數,但仍然讓視圖中的計數器更新?

下面是該問題的一個JS小提琴(看控制檯日誌) https://jsfiddle.net/marmite/nf4c18tx/

回答

0

我想我已經得到了解決有關此特定情況下

我的元素傳遞給指令的鏈接功能。

link: function(scope, el, attrs) { 

然後,而不是結合的計數器的值,我可以手動更新

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

最後,我告訴我的$間隔不invokeApply通過傳遞虛假的第四個參數。

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

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

1

這是正常現象。

角運行稱爲digest loop來檢測和傳播更改。更新由{{ getNumber(number) }}返回的值的唯一方法是通過評估函數getNumber(number),因爲Angular不知道您是否更改了它的返回值。摘要循環由$interval()調用,它是圍繞標準JavaScript setInterval()的封裝。

您可以修改您的代碼以僅使用setInterval(),您可以看到getNumber()不再被調用,因爲沒有什麼可以觸發摘要循環。

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

要回答你的問題:不要從函數返回的數值。我不知道你的用例是什麼,但我認爲你不需要在{{ }}中使用函數調用。它也可能導致重大的性能問題,並且通常避免它會更好。

+0

在我的實際使用情況下,定時器是每一個頁面上。有很多頁面,他們都做各種不同的事情。從ng-repeat函數中返回一個數字只是一個簡單的方法來演示問題。我希望我能做些事情來告訴指令不關心除本身以外的任何事情,因此它不會觸發其他所有的摘要。 – marmite