複数の$ scope属性を見る


回答:


585

AngularJS 1.3以降$watchGroup、一連の式を監視するために呼び出される新しいメソッドがあります。

$scope.foo = 'foo';
$scope.bar = 'bar';

$scope.$watchGroup(['foo', 'bar'], function(newValues, oldValues, scope) {
  // newValues array contains the current values of the watch expressions
  // with the indexes matching those of the watchExpression array
  // i.e.
  // newValues[0] -> $scope.foo 
  // and 
  // newValues[1] -> $scope.bar 
});

7
$ watchCollection( '[a、b]')との違いは何ですか?
カミルトムシク2015年

28
違いは、配列のように見える文字列の代わりに適切な配列を使用できることです
Paolo Moretti

2
同様の問題がありましたが、controllerAsパターンを使用しています。私の場合、修正は変数の前にコントローラーの名前を追加することで構成されていました:$scope.$watchGroup(['mycustomctrl.foo', 'mycustomctrl.bar'],...
morels

1
これは、Angular 1.6では動作しないようです。関数にコンソールログを配置するnewValuesと、プロパティが個別に通常どおり動作するのを監視しながら、oldValuesas およびで1回だけ実行されることがわかりundefinedます。
アレハンドロガルシアイグレシアス

290

AngularJS 1.1.4から使用できるようになりました$watchCollection

$scope.$watchCollection('[item1, item2]', function(newValues, oldValues){
    // do stuff here
    // newValues and oldValues contain the new and respectively old value
    // of the observed collection array
});

ここにプランカーの例

ドキュメントはこちら


109
最初のパラメータは配列ではないことに注意してください。配列のような文字列です。
MK Safi

1
これをありがとう。それが私のために働くなら、私はあなたに千の金貨を与えます-もちろん、仮想のコインです:)
AdityaSaxena '20

5
明確にする(数分かけて理解した)$watchCollectionとは、オブジェクトを渡してオブジェクトのプロパティの変更を監視する$watchGroupことを目的としていますが、個々のプロパティの配列を渡して変更を監視することを目的としています。類似するが異なる問題に取り組むために少し異なります。ふew!
Mattygabe、2015

1
どういうわけか、このメソッドを使用すると、newValuesとoldValuesは常に等しくなります。plnkr.co
edit

ありがとう。それは私の問題を解決しました。$ watchの使用によるパフォーマンスへの影響/問題はありますか?
Syed Nasir Abbas

118

$watch 最初のパラメータは関数にすることもできます。

$scope.$watch(function watchBothItems() {
  return itemsCombinedValue();
}, function whenItemsChange() {
  //stuff
});

2つの組み合わせた値が単純な場合、最初のパラメーターは通常、単なる角度式です。たとえば、firstNameとlastName:

$scope.$watch('firstName + lastName', function() {
  //stuff
});

8
これは、デフォルトでフレームワークに含めることを求めるユースケースのようです。計算されたプロパティでさえ、fullName = firstName + " " + lastName最初の引数として関数を渡す必要があります(のような単純な式ではなく'firstName, lastName')。Angularは非常に強力ですが、パフォーマンスや設計の原則を損なうことのない(思われる)方法で、非常に開発者が使いやすい領域がいくつかあります。
XML

4
まあ$ watchは角度式を取り、それは呼び出されたスコープで評価されます。だからあなたができる$scope.$watch('firstName + lastName', function() {...})。また、2つの時計を実行することもできますfunction nameChanged() {}; $scope.$watch('firstName', nameChanged); $scope.$watch('lastName', nameChanged);。答えに簡単なケースを追加しました。
アンドリュージョスリン2012

「firstName + lastName」のプラスは文字列の連結です。したがって、angularは、連結の結果が現在異なるかどうかを確認するだけです。
mb21

16
文字列の連結には少し注意が必要です。「paran orman」を「para norman」に変更すると、応答がトリガーされなくなります。第1項と第2項の間に「\ t | \ t」のようなディバイダーを置くか、決定的なJSONに固執するのが
ベスト

amberjsは最低ですが、この機能が組み込まれています!その角の男を聞きます。時計を作ることが最も合理的で実行可能な方法だと思います。
アラジンMhemed、2012年

70

これは、実際に機能する元の疑似コードと非常によく似た解決策です。

$scope.$watch('[item1, item2] | json', function () { });

編集:さて、私はこれがさらに良いと思います:

$scope.$watch('[item1, item2]', function () { }, true);

基本的にjsonのステップをスキップしていますが、そもそも最初は馬鹿げているように見えましたが、それなしでは機能しませんでした。それらのキーは、参照の等価ではなくオブジェクトの等価をオンにする、しばしば省略される3番目のパラメーターです。次に、作成した配列オブジェクト間の比較が実際に正しく機能します。


同様の質問がありました。そして、これは私にとって正しい答えです。
Calvin Cheng 2013年

配列式の項目が単純型ではない場合、どちらの場合もわずかなパフォーマンスオーバーヘッドがあります。
2013

それは本当です。コンポーネントオブジェクトの完全な深さの比較を行っています。それはあなたが望むものかもしれませんし、そうでないかもしれません。完全な深さ比較を行わない最新の角度を使用したバージョンについては、現在承認されている回答を参照してください。
Karen Zilles 2013

何らかの理由で、配列に対して$ watchCollectionを使用しようとすると、このエラーTypeError: Object #<Object> has no method '$watchCollection'が発生しましたが、この解決策は問題の解決に役立ちます!
abottoni 2013

クール、あなたもオブジェクト内の値を見ることができます:$scope.$watch('[chaptercontent.Id, anchorid]', function (newValues, oldValues) { ... }, true);
セルジュ・ファンデンOever

15

$ watchGroupの関数を使用して、スコープ内のオブジェクトのフィールドを選択できます。

        $scope.$watchGroup(
        [function () { return _this.$scope.ViewModel.Monitor1Scale; },   
         function () { return _this.$scope.ViewModel.Monitor2Scale; }],  
         function (newVal, oldVal, scope) 
         {
             if (newVal != oldVal) {
                 _this.updateMonitorScales();
             }
         });

1
なぜ使うの_this?スコープは、明示的に定義せずに関数に引き継がれませんか?
sg.cc

1
私はtypescriptを使用していますが、提示されたコードはコンパイルされた結果です。
ヤン・チャン、

12

単純にそれをラップしないのはなぜforEachですか?

angular.forEach(['a', 'b', 'c'], function (key) {
  scope.$watch(key, function (v) {
    changed();
  });
});

これは、実際に値の構成を気にする必要がない、結合された値の関数を提供するのとほぼ同じオーバーヘッドです。


この場合、log()は数回実行されますよね?ネストされた$ watch関数の場合はそうはならないと思います。また、複数の属性を一度に監視するソリューションには含まれません。
John Doe 2013年

いいえ、監視対象のプロパティごとに、変更ごとに1回だけログが実行されます。なぜそれが複数回呼び出されるのですか?
Erik Aigner 2013年

そうです、私たちがそれらすべてを同時に見たいのであれば、それはうまくいきません。
John Doe 2013年

1
もちろん?私のプロジェクトではそうしています。changed()いずれかのプロパティで何かが変更されるたびに呼び出されます。これは、結合された値の関数が提供された場合とまったく同じ動作です。
Erik Aigner 2013年

1
配列内の複数の項目が同時に変更された場合、$ watchは、変更された項目ごとに1回ではなく、ハンドラーを1回だけ起動するという点で少し異なります。
バングル2014年

11

値を組み合わせるための少し安全な解決策は、$watch関数として以下を使用することです。

function() { return angular.toJson([item1, item2]) }

または

$scope.$watch(
  function() {
    return angular.toJson([item1, item2]);
  },
  function() {
    // Stuff to do after either value changes
  });

5

$ watchの最初のパラメーターは、角度式または関数です。$ scope。$ watchのドキュメントを参照してください。$ watchメソッドの動作に関する多くの有用な情報が含まれています。watchExpressionが呼び出されたとき、angularが結果を比較する方法などです。


4

どのように:

scope.$watch(function() { 
   return { 
      a: thing-one, 
      b: thing-two, 
      c: red-fish, 
      d: blue-fish 
   }; 
}, listener...);

2
匿名ハッシュは毎回異なる参照を持っているので、(例のように)truetoへの3番目のパラメーターがないと、毎回起動します。scope.$watchlistener()
PeterV.Mørch、2014年

この解決策は自分の状況に適していることがわかりました。私にとっては、次のようなものでしたreturn { a: functionA(), b: functionB(), ... }。次に、返された新しい値と古い値のオブジェクトを相互にチェックします。
RevNoah 2014年

4
$scope.$watch('age + name', function () {
  //called when name or age changed
});

ここでは、年齢と名前の値の両方が変更されたときに関数が呼び出されます。


2
彼らは結果を連結していない変更されただけで、フィールドになりますので、また必ずこのような場合には、コールバックに角度通ることをnewValueにとOLDVALUE引数を使用しないこと
AkashさんShinde

1

$watchGroupバージョン1.3で導入されたAngular を使用すると、複数の変数を監視できます。単一の$watchGroupブロック $watchGroupが配列を最初のパラメーターとして受け取り、監視するすべての変数を含めることができます。

$scope.$watchGroup(['var1','var2'],function(newVals,oldVals){
   console.log("new value of var1 = " newVals[0]);
   console.log("new value of var2 = " newVals[1]);
   console.log("old value of var1 = " oldVals[0]);
   console.log("old value of var2 = " oldVals[1]);
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.