AngularJS $watch vs $watchCollection: что лучше для производительности?
Для просмотра переменной области объекта объекта $scope.$watch
с objectEquality
установлено значение true ИЛИ $scope.$watchCollection
лучше?
Для переменной объекта $scope
(например, 15 атрибутов, некоторые вложенные 2 уровня в глубину) обновлены с помощью элементов ввода и ng-model
в представлении, насколько плохим является $scope.$watch
с objectEquality
, установленным на true
? Это большая вещь, которую нужно избегать?
Является ли $watchCollection
лучшим решением?
Я ищу легкие победы для повышения производительности моего приложения AngularJS (я все еще придерживаюсь v1.2.2).
// ctrl scope var
$scope.filters = {
name: '',
info: {test: '', foo: '', bar: ''},
yep: ''
// etc ...
}
// ctrl watch ?
$scope.$watch('filters', function(newVal, oldVal) {
if(newVal !== oldVal) {
// call with updated filters
}
}, true);
// or ctrl watch collection ?
$scope.$watchCollection('filters', function(newVal, oldVal) {
if(newVal !== oldVal) {
// call with updated filters
}
});
// view input with ng-model
<input type="text" ng-model="filters.name" />
<input type="text" ng-model="filters.info.test" />
<input type="text" ng-model="filters.yep" />
// etc ...
Ответы
Ответ 1
Функция $watchCollection()
является своего рода промежуточной средой между две $watch()
конфигурации выше. Он более глубокий, чем функция ванили $watch(); но это не так дорого, как функция глубокого равенства $watch()
. Как и функция $watch()
, $watchCollection()
работает путем сравнения ссылок на физические объекты; однако, в отличие от функции $watch(), $watchCollection()
идет одноуровневую глубину и выполняет дополнительную, мелкую контрольную проверку элементы верхнего уровня в коллекции.
см. это объяснение
Ответ 2
$watch() будет запускаться с помощью:
$scope.myArray = [];
$scope.myArray = null;
$scope.myArray = someOtherArray;
$watchCollection() будет вызываться всем выше AND:
$scope.myArray.push({}); // add element
$scope.myArray.splice(0, 1); // remove element
$scope.myArray[0] = {}; // assign index to different value
$watch (..., true) будет запускаться ВСЕМ выше AND:
$scope.myArray[0].someProperty = "someValue";
ТОЛЬКО ОДНА БОЛЬШЕ...
$watch() - единственный, который срабатывает, когда массив заменяется другим с тем же точным контентом. Например:
$scope.myArray = ["Apples", "Bananas", "Orange" ];
var newArray = [];
newArray.push("Apples");
newArray.push("Bananas");
newArray.push("Orange");
$scope.myArray = newArray;
Ниже приведена ссылка на пример JSFiddle, который использует все различные комбинации часов и выводит сообщения журнала, чтобы указать, какие "часы" были вызваны:
http://jsfiddle.net/luisperezphd/2zj9k872/
Ответ 3
$watchCollection
оптимизирован для вектора arrays []
, где элементы могут быть push
и $watch
хороши для объектов ассоциативных массивов {}
$watchCollection
не будет следить за изменениями глубины, как часы с установкой objectEquality в false.
Если вы уже знаете структуру глубины, вы можете ее оптимизировать следующим образом:
// ctrl watch ?
$scope.$watch('filters', function(newVal, oldVal) {
if(newVal !== oldVal) {
// call with updated filters
}
});
// ctrl watch ?
$scope.$watch('filters.info', function(newVal, oldVal) {
if(newVal !== oldVal) {
// call with updated filters
}
});