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
});
上面的示例程式碼自動在頁面上顯示以下圖表( 互動式演示 )。