AngularJS 观察者

示例

观察者需要观察一些值并检测到该值已更改。

在调用或新的观察者之后,将其添加到当前范围内的内部观察者集合中。$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);

  // 删除重复的观察者
  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
});

上面的示例代码自动在页面上显示以下图表(交互式演示)。