2014-07-02 32 views
1

我有一個current-time指令使用$timeout,它似乎是在一個單獨的控制器調用函數。我很困惑這是爲什麼,我以爲控制器包含自己的範圍和相互分離?

基本上,myFunction被當currentTime指令$timeout時調用。這是一件大事嗎?這會對我造成麻煩嗎?有人可以幫我理解這種行爲嗎?這是一個plunker,演示了我正在談論的行爲。

這裏是我的HTML

<html ng-app="myapp"> 

    <head> <!-- using Angular version 1.2.0-rc3 --> </head> 
    <body> 

    <div ng-controller="TimeController"> 
     <span current-time></span> 
    </div> 

    <div ng-controller="MyController"> 
     <span class="grrr">{{myFunction()}}</span> 
    </div> 

    </body> 
</html> 

我的角度代碼:

var myapp = angular.module('myapp', []); 

// just to show that I'm using my currentTime directive in separate controller. 
// but it still happens if remove TimeController. 
myapp.controller('TimeController', ['$scope', function($scope) { 
    console.log('entering TimeController'); 
}]); 

myapp.controller('MyController', ['$scope', function($scope) { 

    $scope.myFunction = function() { 
    console.log('calling myFunction'); 
    return 'myFunction was last called @ ' + new Date().toString(); 
    }; 

}]); 

// continuous update for time 
myapp.directive('currentTime', ['$timeout', function($timeout) { 

    return function(scope,element,attrs) { 
    function updateTime() { 
     $timeout(function() { 
     element.text(new Date().toString()); 
     updateTime(); 
     }, 1000); 
    }; 
    console.log('start clock'); 
    updateTime(); 
    }; 
}]); 

回答

5

TL:DR;

您的指令更改爲

$timeout(function() { 
     element.text(new Date().toString()); 
     updateTime(); 
    }, 1000, false); 

而且它也不會觸發您myFunction()

說來話長

當你做到這一點

<span class="grrr">{{myFunction()}}</span> 

ÿ你基本上告訴Angular,span的內容應該總是等於調用myFunction()的結果。現在,Angular不知道你的函數依賴於什麼類型的變量來返回結果,所以無論什麼時候改變了,它都需要再次調用該函數來查看它是否返回其他東西(這稱爲髒檢查) 。記住這一點,一旦我們看到指令,這將是重要的。

在指令中,您每秒都會運行$timeout。這觸發了一個$digest循環,這基本上是Angular檢測事情是否發生變化的方法。在這樣做的過程中,它正在檢查所有的範圍,這意味着它也會調用你的myFunction()來查看指令是否影響了這個。這就是爲什麼它不斷被調用。

現在,如果你不想要這種行爲,你可以綁定到一個變量而不是一個函數,或者如果你像我一樣好奇地轉向源代碼$timeout。我想你也可以看看documentation,但說實話,大部分的Angular文檔都不是那麼好,所以我通常首先選擇源代碼。

有一個可選標誌(這個文件甚至被記錄在案)叫做invokeApply,如果你設置爲false,那麼$timeout不會觸發髒檢查。

+0

太棒了,現在有道理。謝謝! – fbynite

2

這就是$摘要循環的工作方式。當$摘要被觸發時,角將遍歷所有$ watch表達式並確定它們是否已經改變。這發生在所有作用域上的所有$ watch表達式 - 一個稱爲髒檢查的進程。

之所以myFunction的()被調用是因爲上面有一個隱含的$手錶作爲綁定表達式的結果:

{{myFunction()}} 

這是正常的,沒有什麼可擔心。

定期觸發$ digest循環的原因是由於您的$超時函數。默認情況下,它會在$ apply塊中調用你的超時函數,然後觸發$摘要。您可以通過將false作爲第三個參數傳遞給$ timeout來禁用此行爲。

我想建議您使用$interval而不是$timeout。它更適合這個。

相關問題