325

私のスコープにはオブジェクトの配列があり、各オブジェクトのすべての値を監視したいと考えています。

これは私のコードです:

function TodoCtrl($scope) {
  $scope.columns = [
      { field:'title', displayName: 'TITLE'},
      { field: 'content', displayName: 'CONTENT' }
  ];
   $scope.$watch('columns', function(newVal) {
       alert('columns changed');
   });
}

しかし、値を変更すると、たとえば に変更TITLEしてTITLE2も、alert('columns changed')決してポップされません。

配列内のオブジェクトを深く監視する方法は?

ライブデモがあります: http://jsfiddle.net/SYx9b/

4

10 に答える 10

539

の 3 番目の引数を$watchに設定できtrueます。

$scope.$watch('data', function (newVal, oldVal) { /*...*/ }, true);

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchを参照してください

Angular 1.1.x 以降では、 $watchCollection を使用して、コレクションの浅い監視 (「最初のレベル」のみ) を監視することもできます。

$scope.$watchCollection('data', function (newVal, oldVal) { /*...*/ });

https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchCollectionを参照してください

于 2013-02-05T18:04:20.910 に答える
51

$watch でオブジェクトを深く掘り下げると、パフォーマンスに影響があります。場合によっては (たとえば、変更がプッシュとポップのみの場合)、array.length などの簡単に計算できる値を $watch したい場合があります。

于 2013-08-08T06:43:11.383 に答える
43

1 つの配列のみを監視する場合は、次のコードを簡単に使用できます。

$scope.$watch('columns', function() {
  // some value in the array has changed 
}, true); // watching properties

ただし、これは複数の配列では機能しません。

$scope.$watch('columns + ANOTHER_ARRAY', function() {
  // will never be called when things change in columns or ANOTHER_ARRAY
}, true);

この状況に対処するために、私は通常、監視したい複数の配列を JSON に変換します。

$scope.$watch(function() { 
  return angular.toJson([$scope.columns, $scope.ANOTHER_ARRAY, ... ]); 
},
function() {
  // some value in some array has changed
}

@jssebastian がコメントで指摘したように、「$」で始まるメンバーやその他のケースも処理できるJSON.stringifyため、より好ましい場合があります。angular.toJson

于 2013-02-05T16:34:37.257 に答える
21

Angular 1.1.x 以降では、$watch ではなく$watchCollectionを使用できるようになったことに注意してください。$watchCollection は浅いウォッチを作成しているように見えますが、期待どおりにオブジェクトの配列では機能しません。配列への追加と削除は検出できますが、配列内のオブジェクトのプロパティは検出できません。

于 2013-08-29T18:35:14.963 に答える
12

$watchCollectionは、やりたいことを実現します。以下は、angularjs の Web サイトhttp://docs.angularjs.org/api/ng/type/$rootScope.Scopeからコピーした例です 。これは便利ですが、特に大規模なコレクションを表示する場合は、パフォーマンスを考慮する必要があります。

  $scope.names = ['igor', 'matias', 'misko', 'james'];
  $scope.dataCount = 4;

  $scope.$watchCollection('names', function(newNames, oldNames) {
     $scope.dataCount = newNames.length;
  });

  expect($scope.dataCount).toEqual(4);
  $scope.$digest();

  //still at 4 ... no changes
  expect($scope.dataCount).toEqual(4);

  $scope.names.pop();
  $scope.$digest();

  //now there's been a change
  expect($scope.dataCount).toEqual(3);
于 2014-03-23T05:23:11.237 に答える
4

このソリューションは私にとって非常にうまく機能しました。私はディレクティブでこれを行っています:

scope.$watch(attrs.testWatch, function() {.....}, true);

true は非常にうまく機能し、すべての変更 (フィールドの追加、削除、または変更) に反応します。

これは、それを使って遊ぶための作業プランカーです。

AngularJS で配列を深く監視する

これがお役に立てば幸いです。ご不明な点がございましたら、お気軽にお問い合わせください:)

于 2013-10-10T02:34:18.640 に答える
4

私の場合、他のいくつかのコントローラーによっても監視されるアドレス オブジェクトを含むサービスを監視する必要がありました。「true」パラメーターを追加するまでループに陥っていました。これは、オブジェクトを監視する際の成功の鍵と思われます。

$scope.$watch(function() {
    return LocationService.getAddress();
}, function(address) {
    //handle address object
}, true);
于 2014-01-09T19:29:20.933 に答える