Watcher

觀察者需要觀察一些值並檢測到該值是否已更改。

在呼叫 $watch()$watchCollection 後,新的觀察者在當前範圍內新增到內部觀察者集合。

那麼,觀察者是什麼?

Watcher 是一個簡單的函式,在每個摘要週期呼叫,並返回一些值。Angular 檢查返回的值,如果它與前一次呼叫的不一樣 - 將在第二個引數中傳遞給函式 $watch()$watchCollection 的回撥將被執行。

(function() {
  angular.module("app", []).controller("ctrl", function($scope) {
    $scope.value = 10;
    $scope.$watch(
      function() { return $scope.value; },
      function() { console.log("value changed"); }
    );
  }
})();

觀察者是表演殺手。你擁有的觀察者越多,他們製作摘要迴圈的時間越長,UI 越慢。如果觀察者檢測到變化,它將啟動摘要迴圈(在所有螢幕上重新計算)

在 Angular 中有三種方法可以手動監視變數的變化。

$watch() - 只關注價值變化

$watchCollection() - 手錶收藏變化(手錶超過常規$ watch)

$watch(..., true) - 儘可能避免這種情況,它將執行深度觀察並將殺死效能(手錶超過 watchCollection)

請注意,如果你在檢視中繫結變數,則表示你正在建立新的觀察者 - 使用 {{::variable}} 不建立觀察者,尤其是在迴圈中

因此,你需要跟蹤你使用的觀察者數量。你可以使用此指令碼統計觀察者(歸功於 @Words Like Jared - 如何計算頁面上的手錶總數?

(function() {
  var root = angular.element(document.getElementsByTagName("body")),
      watchers = [];

  var f = function(element) {

    angular.forEach(["$scope", "$isolateScope"], function(scopeProperty) {
      if(element.data() && element.data().hasOwnProperty(scopeProperty)) {
        angular.forEach(element.data()[scopeProperty].$$watchers, function(watcher) {
          watchers.push(watcher);
        });
      }
    });

    angular.forEach(element.children(), function(childElement) {
      f(angular.element(childElement));
    });

  };

  f(root);

  // Remove duplicate watchers
  var watchersWithoutDuplicates = [];
  angular.forEach(watchers, function(item) {
    if(watchersWithoutDuplicates.indexOf(item) < 0) {
      watchersWithoutDuplicates.push(item);
    }
  });

  console.log(watchersWithoutDuplicates.length);

})();

如果你不想建立自己的指令碼,那麼有一個名為 ng-stats 的開源實用程式,它使用嵌入頁面的實時圖表,讓你深入瞭解 Angular 正在管理的手錶數量,以及消化週期的頻率和持續時間。該實用程式公開了一個名為 showAngularStats 的全域性函式,你可以呼叫該函式來配置圖表的工作方式。

showAngularStats({
  "position": "topleft",
  "digestTimeThreshold": 16,
  "autoload": true,
  "logDigest": true,
  "logWatches": true
});

上面的示例程式碼自動在頁面上顯示以下圖表( 互動式演示 )。

StackOverflow 文件