angular1.x 髒檢測

寫在前面

  雙向綁定是angular的大亮點,而後支撐它的就是髒檢測。一直對髒檢測都有一些理解,卻沒有比較系統的概念。html

  如下是我閱讀網上博文以及angular高級程序設計的理解與總結。app

  接收指導與批評。函數

髒檢查:

  將原對象賦值一份快照。在某個時間,遍歷比較這個對象和快照(新舊值),若是不同就執行執行某些操做。spa

angular中的髒檢查:

  1.不會檢查全部的對象。當對象被綁定到html會檢查,手動$scope.$watch()的會檢查。檢查的手段就是爲這些對象建立(watcher)對象。並push到(watcher隊列) 2.不會檢查全部的屬性。只要被綁定的屬性纔會被註冊。 在angular程序初始化時,會將綁定的對象的屬性添加爲監聽對象(watcher),也就是說一個對象綁定了N個屬性,就會添加N個watcher。設計

angular註冊watcher對象雙向綁定

  angualr會爲每個綁定到DOM的對象/對象的屬性,建立一個watcher對象,(使用$scope.$watch()方法也會建立),watcher對象有好幾個屬性,(下面是筆者理解抽象出來的,並非真的屬性名code

watch = {
  name:'',      //當前的watch 對象 觀測的數據名,鎖定監聽的是什麼
  getNewValue:function($scope){ //獲取監聽屬性的最新值
      ...
      return newValue;
      },
  listener:function(newValue,oldValue){  // 先比較新值與舊值判斷是否繼續執行,通常負責使用新值更新DOM頁面,也能夠是$watch方法註冊的回調函數
      ...
  }
}

  $$watchers的watcher屬性截圖htm

 

$scope.$$watchers隊列對象

  每個建立好的watcher對象會被push到各自的controller做用域的$scope.$$watchers隊列裏面。
  髒檢測就是遍歷watchers的過程。blog


髒檢測經過兩個方法觸發:$digest(), $apply()
  $digest:是遍歷當前做用域以及其子做用域的$$watchers隊列,並執行其listener。
  $apply:是對$digest()的封裝。接受一個函數參數(包含脫離angular環境的邏輯,須要卻不會本身觸發髒檢測, 因此$apply幫他觸發一下。),$apply在執行了參數函數以後自動調用 $rootScope.$digest (就是從更做用於開始遍歷每個$scope.$$watchers隊列)


  若是你對本身的邏輯比較清楚,能夠不使用$apply,改用$scope.$digest(),只遍歷當前與其子做用域。不用從rootScope開始

  若是不是很瞭解邏輯,建議仍是使用$apply()從rootScope開始,避免須要更新的值沒有被更新,而且$apply會把參數函數放在try...catch裏面,若是邏輯發生錯誤。會把錯誤傳給$exceptionHandler service來處理。

$scope.data = 0;
$scope.data2 = 0;
// code 1
setInterval(function() {
  $scope.$apply(function() {
    $scope.data++;
    console.log('first:', $scope.data)
  });
}, 2000);

// code 2
setInterval(function() {
  $scope.data2++;
  console.log('second:', $scope.data2)
  $scope.$apply();    // 對比code1,少了try...catch
  // $scope.$digest();  // 只遍歷當前及其子做用域的$$watchers隊列
},2000)

 

 

一次髒檢測中$digest()執行的次數?

  在一個髒檢測中,digest至少會執行兩次

  由於某一個監聽屬性的listener可能會改變另外一個監聽屬性的值。所以,angular須要在一次$digest()以後判斷這一輪digest中時候有沒有屬性發生變化並執行了listener,若是有,angular必須再次調用$digest();當已經連續觸發了10次$digest(),若還有屬性發生變化,angular就會認爲你的邏輯錯了並console報告。所以在$scope.$watch時要本身多加註意理解好邏輯問題。

何時會觸發髒檢測?

  好像很多人有一個誤區。angular是定時執行髒檢測的!!!!(我以前還問過,angular設置多久執行一次髒檢測,無言以對)

  angular並非定時的。會觸發髒檢測的有如下:

    1. controller 初始化
    2. 幾乎全部ng-開頭的事件(ng-click,ng-change...)
    3. http請求
    4. $timeout,$interval
    5. 手動調用$apply(), $digest()

  回頭想一想,若是是定時的,怎麼會有脫離angualr環境的說法呢?

相關文章
相關標籤/搜索