AngularJS $watch 与 $watchCollection:性能哪个更好?

Posted

技术标签:

【中文标题】AngularJS $watch 与 $watchCollection:性能哪个更好?【英文标题】:AngularJS $watch vs $watchCollection: which is better for performance? 【发布时间】:2014-12-19 13:17:04 【问题描述】:

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

对于使用输入元素和视图中的ng-model 更新的$scope 对象变量(如15 个属性,一些嵌套2 级深),$scope.$watchobjectEquality 设置为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() 是 一级深度并执行额外的、浅层的参考检查 集合中的***项目。

see this explanation

【讨论】:

【参考方案2】:

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

$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
    
  );

【讨论】:

【参考方案3】:

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

【讨论】:

不确定$watchCollection(...,true) 是什么意思,因为该函数不像$watch 那样采用布尔参数(即objectEquality)。 @tamakisquare 我进行了更正和其他更新以使其更清晰。包括更新 JS Fiddle。 @luisperezphd - 关于您的最新更新,$watchCollection() 也会被解雇,因为 $watch()$watchCollection() 都比较对象引用,而不是像 $watch(... true) 那样比较对象相等性 @tamakisquare 你可以创建一个 JS Fiddle 来说明这一点。根据我的回答,我在 JS Fiddle 中有这种情况,$watchCollection() 没有触发。该示例使用 AngularJS 1.2.1。 @luisperezphd - 我想我昨晚在尝试$watchCollection 时一定是搞混了其他东西,因为就像你说的那样,我现在无法用$watchCollection() 重现它。很抱歉误报。我的错。

以上是关于AngularJS $watch 与 $watchCollection:性能哪个更好?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:清除 $watch

Angular JS $watch 与 $on

angularJS 里的$watch的用法

AngularJS $watch 的 Angular 等价物是啥?

Angularjs:“控制器作为语法”和 $watch

第一次更新后,AngularJS $watch 数组失败