45

对于观察对象范围变量,$scope.$watch设置objectEquality为 true还是$scope.$watchCollection更好?

对于$scope使用输入元素和视图更新的对象变量(如 15 个属性,一些嵌套的 2 层深),设置为ng-model有多糟糕?这是要避免的大事吗?$scope.$watchobjectEqualitytrue

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

3 回答 3

187

$watch()将由以下触发:

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

$watchCollection()将由以上所有内容触发并且:

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

$watch(..., true)将由以上所有内容触发并且:

$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/

于 2015-03-21T23:30:45.037 回答
39

该功能是上述两种配置$watchCollection()之间的一种中间地带。$watch()它比普通的 $watch() 函数更深入;但是,它并不像深度平等$watch()函数那样昂贵。与$watch()功能一样, $watchCollection()作品通过比较物理对象引用;但是,与该$watch()函数不同的是,该函数$watchCollection()会深入一层,并对集合中的顶级项目执行额外的、浅层的引用检查。

看到这个解释

于 2014-10-23T19:06:05.813 回答
3

$watchCollection针对arrays []可以推送元素的向量进行了优化

并且$watch适用于关联数组对象 {}

$watchCollection不会关注深度变化,就像将 objectEquality 设置为 false 的 watch。

如果您已经知道深度的结构,您可以像这样优化:

  // 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
    }
  });
于 2014-12-03T09:49:53.593 回答