天天看點

$scope裡的$apply、$digest方法

什麼是scope

官方文檔的解釋:

scope is an object that refers to the application model. It is an execution context for expressions. Scopes are arranged in hierarchical structure which mimic the DOM structure of the application. Scopes can watch expressions and propagate events.

Scopes can be nested to limit access to the properties of application components while providing access to shared model properties. Nested scopes are either "child scopes" or "isolate scopes". A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope" does not. See isolated scopes for more information.

Scopes provide context against which expressions are evaluated. For example {{username}} expression is meaningless, unless it is evaluated against a specific scope which defines the username property.

scope是一個指向應用model的object,也是表達式的執行上下文。

scope被放置于一個類似應用的DOM結構的層次結構中。

什麼是Scope characteristics

官方文檔的解釋:

Scopes provide APIs ($watch) to observe model mutations.

Scopes provide APIs ($apply) to propagate any model changes through the system into the view from outside of the "Angular realm" (controllers, services, Angular event handlers).

示例程式:

<body>

<div ng-app="">

    <div ng-controller="firstController">

        {{date}}

    </div>

</div>

<script type="text/javascript" src="app/index.js"></script>

<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>

</body>

</html>

JS檔案:

var firstController;

firstController = function ($scope) {

     $scope.date = new Date();

     setInterval(function(){

      $scope.date= new Date();

  },1000)

}

此時,在JS檔案中寫明了希望時間一秒鐘變化一次。但是此時對應的html檔案裡是不會變化的。是以VIEW中不會發生改變。

model裡面改變了,怎麼取通知view也去update呢?

angular怎麼樣才能知道變量發生了改變

要知道變量是否改變,方法不外乎兩種

  1. 能通過固定的接口才能改變變量的值。比如說隻能通過set()設定變量的值,set被調用時比較一下就知道了(這種方法寫法繁瑣)。
  2. 髒檢查(dirty check),将原對象複制一份快照,在某個時間,比較現在對象與快照的值,如果不一樣就表明發生變化,這個政策要保留兩份變量,而且要周遊對象,比較每個屬性,這樣就會有性能問題。

Angular的實作是使用髒檢查

  • angular的政策
    1. 不會髒檢查所有的對象,當對象被綁定到html中(比如執行個體程式的date對象),這個對象添加為檢查對象(watcher)。
    2. 不會髒檢查所有的屬性,同樣當屬性被綁定後,這個屬性會被列為檢查的屬性
  • 在angular程式初始化時,會将綁定的對象的屬性添加為監聽對象(watcher),也就是說一個對象綁定了N個屬性,就會添加N個watcher。

什麼時候執行髒檢查

angular所系統的方法中都會觸發比較事件,比如:controller初始化的時候,所有以ng-開頭的事件執行後,都會觸發髒檢查。

執行個體中的代碼,此時時間一秒鐘發生一次改變(也确實是改變了,但是沒有觸發髒檢查。是以不會觸發view上的對象去改變)

 setInterval(function(){

       $scope.date= new Date();

  },1000)

手動觸發髒檢查

$apply僅僅隻是進入angular context,然後通過$digest去觸發髒檢查

 setInterval(function(){
    $scope.$apply(function(){
      $scope.date= new Date();
    })
  },1000)

$apply如果不給參數的話,會檢查改$scope裡所有的監聽的屬性,推薦給上參數

$digest()

  • 所屬的scope和其所有子scope的髒檢查,髒檢查又會觸發$watch(),整個angular雙向綁定機制就活了起來
  • 不建議直接調用$digest(),而應該使用$apply,$apply其實不能把信直接送給$digest, 之間還有$eval門衛把關,如果$apply帶的表達方式不合法,$eval會把錯誤送交$exceptionHandler,合法才觸發digest,是以更安全

繼續閱讀