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
});
上面的示例代码自动在页面上显示以下图表( 交互式演示 )。