AngularJS $watch vs $watchCollection: что лучше для производительности? - программирование
Подтвердить что ты не робот

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 ...  
4b9b3361

Ответ 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
    }
  });