AngularJS $scope裡面的$watch(),$digest()和$apply()是AngularJS的核心函數,學習AngularJS必須理解這幾個函數。
在綁定$scope中的變數到view的時候,AngularJS自動在內部建立一個"Watch"。"Watch"用於監聽AngularJS scope中變數的改變。可以通過調用$scope.$watch()這個方法來建立"Watch"。
$scope.$digest()函數會逐一查看所有的watches,並檢測其所監聽的$scope中的變數是否改變。如果變數發生改變,會調用該變數對應的監聽函數。監聽函數可以實現很多操作,比如讓html裡面的text文本顯示最新的變數值。可見,$scope.$digest是可以觸發資料繫結更新的。
大部分情況下,AngualrJS會自動調用$scope.$watch()和$scope.$digest()函數,但是在某些情況下,我們需要手動調用他們,因此,有必要瞭解他們是怎麼工作的。
$scope.$apply()這個函數會先執行一些代碼,之後在調用$scope.$digest()。所有的watches會被檢測一次,相應的監聽函數也會被執行。$scope.$apply()在AngularJS與其它javascript代碼整合時是很有用的。
接下來我們具體的講解下$watch(), $digest() 和 $apply()。
$watch()
$watch(watchExpression, listener, [objectEquality])
watchExpression:監聽對象,可以是string或者function(scope){}
listener:監聽對象發生改變時執行的回呼函數function(newVal,oldVal,scope){}
objectEquality:是否深度監聽,如果設定為true,它告訴Angular檢查所監控的對象中每一個屬性的變化。如果你希望監控數組的個別元素或者對象的屬性而不是一個普通的值, 那麼你應該使用它。(預設值:false)
$digest()
檢測當前scope以及子scope中所有的watches,因為監聽函數會在執行過程中修改model(scope中的變數),$digest()會一直被調用直到model沒有再變。當調用超過10次時,$digest()會拋出一個異常"Maximum iteration limit exceeded',以此來防止程式進入一個死迴圈。
$apply()
$apply([exp])
exp:string或者function(scope){}
$apply()生命週期虛擬碼示意圖如下
function $apply(expr) { try { return $eval(expr); } catch (e) { $exceptionHandler(e); } finally { $root.$digest(); }}
Example
下面我們通過一個例子來說明$watch,$digest和$apply。
<script>var module = angular.module("myapp", []);var myController1 = module.controller("myController", function($scope) { $scope.data = { time : new Date() }; $scope.updateTime = function() { $scope.data.time = new Date(); } document.getElementById("updateTimeButton") .addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); });});</script><body ng-app="myapp"><div ng-controller="myController"> {{data.time}} <br/> <button ng-click="updateTime()">update time - ng-click</button> <button id="updateTimeButton" >update time</button></div></body>
這段代碼會綁定$scope.data.time到HTML中顯示出來,同時這個綁定會自動建立一個watch來監聽$scope.date.time的變化。此外,這裡還有2個按鈕,第一個按鈕是通過ng-click Directive來調用$scope.updateTime方法,之後AngularJS會自動執行$scope.$digest()使最新的時間顯示到HTML中。第二個按鈕是通過javascript代碼添加一個點擊事件,以此來更新HTML中的時間。但是第二個按鈕是不能工作的,它的解決辦法是在點擊事件的最後手動的去調用$scope.$digest()方法,如下:
document.getElementById("updateTimeButton") .addEventListener('click', function() { console.log("update time clicked"); $scope.data.time = new Date(); $scope.$digest();});
另外一個解決辦法是調用$scope.$apply(),如下:
document.getElementById("updateTimeButton") .addEventListener('click', function() { $scope.$apply(function(){ console.log("update time clicked"); $scope.data.time = new Date(); } );});
以上就是本文的全部內容,希望對大家的學習有所協助。