AngularJS 中的 $digest() 和 $apply()

1. 何時須要人爲調用 $apply()?

AngularJS 只會關心在 AngularJS 的執行上下文中 發生的數據模型(model)的變化(好比: 改變數據的代碼在 $apply() 裏面)。AngularJS 內建的指令 也會自動觸發 $digest 循環, 因此任何數據模型(model)的改變也都會反映到視圖中。 可是, 若是更改一個 不在 AngularJS 執行上下文中 的數據模型(model), 就須要人爲的調用 $apply() 來提醒 AngularJS 數據發生變化了。javascript

例如, 但使用JavaScript的 setTimeout() 函數來更新一個數據模型的時候, AngularJS 就沒有辦法知道你改變了數據模型。這種狀況下, 就須要調用 $apply() 來觸發 $digest 循環了。相似的, 若是自定義了一個指令, 這個指令設置了一個 DOM 事件監聽器, 更改數據模型的代碼在時間處理函數裏, 那麼也須要調用 $apply() 來保證更改能反映出來。html

DEMO:java

HTML 代碼:app

<!DOCTYPE html>
<html lang="en">

<head>
    <title>demo</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <div ng-app="myApp">
        <div ng-controller="myController">
            Delayed Message: {{message}}
        </div>
    </div>
    <script src="js/angular.js">
    </script>

    <script src="js/apply.js"></script>
</body>

</html>

JS 代碼:函數

var myApp = angular.module('myApp', [])

myApp.controller('myController', ['$scope', '$timeout', function($scope, $timeout) {
    $scope.getMessage = function() {

        // 方法1:
        setTimeout(function() {
            // 把須要寫的邏輯放入$apply函數內
            $scope.$apply(function() {
                $scope.message = 'Fetched after 3 seconds'
                console.log('message: ', $scope.message);
            })
        }, 2000)

        // 方法2:

        // $timeout(function() {
        //     $scope.message = 'Fetched after 3 seconds'
        //     console.log('message: ', $scope.message);
        // }, 2000)

        // 方法3:

        // setTimeout(function() {
        //     $scope.message = 'Fetched after 3 seconds'
        //     console.log('message: ', $scope.message);
        //     $scope.$apply() // 這裏觸發了 $digest循環
        // }, 2000)
    }

    $scope.getMessage()
}])

注意:code

但須要延時的時候, 儘量的使用 $timeout, 這樣, 就不用人爲的去調用 $apply() 了。
在調用 $apply() 的時候, 應該老是要傳入函數參數, 由於當爲 $apply() 傳入函數的時候, 這個函數在調用的時候是包含在 try..catch 中, 而且任何發生的異常都可以被 $exceptionHandler 服務所接收。htm

2. $digest 循環要執行多少次呢

$digest 循環並不僅是運行一次。在當前循環結束後, 它會再次啓動來檢查是否有數據發生變化, 這被叫作 髒檢查$digest 循環會一直保持循環直到再也沒有數據模型發生改變, 或者達到最大的循環次數(10次)。事件

注意: $digest 至少會循環兩次即便監聽函數沒有更改任何數據模型。它會多運行一次以確保沒有數據發生變化。ip

3. 總結

若是 AngularJS 不能檢測到你的更改, 那麼就必須人爲調用 $apply()get

相關文章
相關標籤/搜索