16

基本的に私はこれが欲しいhttp://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=previewしかし、何かを変更しても時計が起動しません..

私はこれがうまくいったことを知っています

$scope.$watch('stuff', function (newVal, oldVal) {
    console.log(oldVal, newVal);

}, true);

しかし、私は時計の中でいくつかの合計をしたいので、不必要にループスルーしたり、変更されなかった値を再合計したりしたくありません..

//編集 - plnkr の例は、ng-repeat 以外の別の入力からの合計数 (何かと何かの合計) を変更するなど、実際のアプリから抽出したものにすぎず、行の追加と削除などを行うことができます。 .

4

4 に答える 4

6

配列の大きさによっては、非常に負担がかかる可能性があるため、監視はしません。代わりに、フィルターを作成します。

HTML:

Sum of something is: {{ stuff | sum:'something' }}<br/>
Sum of somethingelse is: {{ stuff | sum:'somethingelse' }}

Javascript:

.filter("sum", function(){
    return function(input, params){
        var totalSum = 0;
        for(var x = 0; x < input.length; x++){
            totalSum += input[x][params];
        }
        return totalSum;
    }
})

plnkr: http://plnkr.co/edit/p6kM3ampSuMXnwqcteYd?p=preview

于 2013-03-20T12:57:08.767 に答える
4

あなたの問題に対するこの解決策を思いついた後、私はいたるところで笑っています. このソリューションは、個々のオブジェクトを監視するだけでなく、合計のために残りのオブジェクトを完全にループすることもありません。

http://plnkr.co/edit/oPWobcLLtJlxs5vjTYyc?p=preview

app.controller('MainCtrl', function($scope) {
  $scope.stuff = STUFF;
  var i;
  $scope.sumOfSomething = 0;
  $scope.sumOfSomethingElse = 0;

  for(i=0;i < $scope.stuff.length;i++ ){
    $scope.$watch('stuff['+i+'].something', function (newVal,oldVal) {
      // happens when the watch is registered.
      if(oldVal === newVal){
        $scope.sumOfSomething += +newVal;
        return;
      }
      if(newVal){
        $scope.sumOfSomething += + (newVal - oldVal);
      }
    });

    $scope.$watch('stuff['+i+'].somethingelse', function (newVal,oldVal) {
      // happens when the watch is registered. 
      if(oldVal === newVal){
        $scope.sumOfSomethingElse += +newVal;
        return;
      }

      if(newVal){
        $scope.sumOfSomethingElse += + (newVal - oldVal);
      }

    });  
  }
});

ちなみに、 に多数のオブジェクトがある場合、このソリューションがどの程度最適になるかはわかりませんSTUFF。また、オブジェクトの数がSTUFF変更される場合、これはそのままでは機能しません。基本的に行っていることは、angular のダーティ チェック ループを使用して合計を行うことです。

また、ウォッチ リスナーでの newVal と oldVal の順序にも注目してください。あなたの注文は間違っています。

于 2013-03-20T12:16:07.517 に答える
3

$watch()角度式を使用するため、カスタム ウォッチャー関数を使用できます。あなたの場合、変更を監視する最も簡単な方法は、関心のあるすべてのフィールドを合計してから、Angular にとって適切で効率的な単一の数値を返すことです。合計をレンダリングする準備が整います。

var sumThings = function(obj, field) {
  var val = 0;
  obj.forEach(function(o) {
    val += parseInt(o[field]);
  });
  return val;
};

$scope.$watch(function() { return sumThings($scope.stuff, "something")}, function (newVal, oldVal) {    //console.log("watchExpression('something') fired!", oldVal, newVal);
  $scope.somethingSum = newVal;
});

$scope.$watch(function() { return sumThings($scope.stuff, "somethingelse")}, function (newVal, oldVal) {
  $scope.somethingelseSum = newVal;
});

基本的に、合計を行うことで、独自のダーティチェックを行っています。$watch(STUFF, true)オブジェクトがここで示したよりも複雑な場合よりも効率的です。

更新された plnkr : http://plnkr.co/edit/d7CvERu3XGkub4l6f1yw?p=preview

于 2014-02-12T22:40:18.587 に答える
1

わかりましたら、内側のオブジェクトが変更されたときに合計somethingしたいだけです。somethingelseまた、変更が内部オブジェクトの 1 つにある場合は、他のすべての内部オブジェクトをループしたくありません。

まあ、あなた$watchは発砲していませstuff.propertystuff.*.something

オブジェクトが配列からプッシュまたはプルされる瞬間がわかっている場合は、各オブジェクトを配列$scope.$watch(object, function(){}, true)に挿入する前後に個別に適用できます。この瞬間がわからない場合は$watch、アレイ全体が必要になります。変更が発生した場合は、すべての登録解除関数と$watchそれらすべてを 1 つずつ実行します。

とにかく、最近のブラウザーのループは非常に高速であり、大量の計算を行っていて、何百万ものオブジェクトがある場合を除いて (これは既にメモリの問題だったはずです)、おそらくそれでうまくいくでしょう。したがって、$watchシステムのパフォーマンスを構成する可能性のある非常に重い計算がある場合にのみ、それらすべてを個別に処理する必要があります。

于 2013-03-20T12:10:28.320 に答える