web-dev-qa-db-fra.com

AngularJS $ watch vs $ watchCollection: quel est le meilleur pour la performance?

Pour regarder une variable de portée d'objet, $scope.$watch Avec objectEquality défini sur true OR $scope.$watchCollection Est meilleur?)

Pour une variable d'objet $scope (Comme 15 attributs, certains profonds imbriqués) mise à jour avec des éléments d'entrée et ng-model Dans la vue, quelle est la valeur de $scope.$watch Avec objectEquality réglé sur true? Est-ce une grosse chose à éviter?

$watchCollection Est-il une meilleure solution?

Je recherche des gains faciles pour améliorer les performances de mon application AngularJS (je suis toujours bloqué sur la 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 ...  
40
user12121234

La fonction $watchCollection() est une sorte de mi-terrain entre les deux configurations $watch() ci-dessus. C'est plus en profondeur que la fonction Vanilla $ watch (); mais ce n'est pas aussi cher que la fonction d'égalité profonde $watch(). Comme la fonction $watch(), la fonction $watchCollection() fonctionne en comparant les références d'objet physique; Toutefois, contrairement à la fonction $watch(), la $watchCollection() a une profondeur d'un niveau et effectue une vérification de référence supplémentaire peu profonde des éléments de niveau supérieur de la collection.

voir cette explication

38
Narek Mamikonyan

$ watch () sera déclenché par:

$scope.myArray = [];
$scope.myArray = null;
$scope.myArray = someOtherArray;

$ watchCollection () sera déclenché par tout ce qui précède AND:

$scope.myArray.Push({}); // add element
$scope.myArray.splice(0, 1); // remove element
$scope.myArray[0] = {}; // assign index to different value

$ watch (..., true) sera déclenché par TOUT ci-dessus ET:

$scope.myArray[0].someProperty = "someValue";

JUSTE UNE CHOSE DE PLUS ...

$ watch () est le seul qui se déclenche lorsqu'un tableau est remplacé par un autre avec le même contenu exact. Par exemple:

$scope.myArray = ["Apples", "Bananas", "Orange" ];

var newArray = [];
newArray.Push("Apples");
newArray.Push("Bananas");
newArray.Push("Orange");

$scope.myArray = newArray;

Vous trouverez ci-dessous un lien vers un exemple de JSFiddle qui utilise les différentes combinaisons de surveillance et génère des messages de journal pour indiquer les "surveillances" déclenchées:

http://jsfiddle.net/luisperezphd/2zj9k872/

180
Luis Perez

$watchCollection est optimisé pour le vecteur arrays [] où les éléments peuvent être Push

et $watch est bon pour les objets de tableaux associatifs {}

$watchCollection ne surveille pas les changements de profondeur, est comme une montre avec objectEquality défini sur false.

Si vous savez déjà structurer la profondeur, vous pouvez optimiser comme ceci:

  // 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
    }
  });
3
Mihai Nistor