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 文档