基本的にこれが欲しい http://plnkr.co/edit/3yfXbo1c0llO40HZ8WNP?p=preview でも、何かを変更しても時計が起動しない。
私はこれがうまくいったことを知っています
$scope.$watch('stuff', function (newVal, oldVal) {
console.log(oldVal, newVal);
}, true);
しかし、私は時計の内部でいくつかの要約を行いたいので、変更されなかった値を不必要にループしたり、再開したりしたくありません。
//編集-plnkrの例は実際のアプリからの抜粋であり、合計数(何かと何かの合計)の変更など、行の追加と削除などを行うことができます。 ng-repeatの外部の別の入力から..
アレイの大きさによっては、非常に負担がかかる可能性があるため、監視は行いません。代わりに、フィルターを作成します。
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;
}
})
あなたの問題に対するこの解決策を思いついた後、私はあちこちで笑っています。このソリューションは、個々のオブジェクトを監視するだけでなく、合計のために残りのオブジェクトを完全にループすることもありません。
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の順序にも注意してください。あなたの注文は間違っています。
$watch()
はangular式を使用するため、カスタムウォッチャー関数を使用できます。あなたの場合、変更を監視する最も簡単な方法は、現在のすべてのフィールドを合計することです。興味がある場合は、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)
よりも効率的です。
ええと、もし私がそれを手に入れたら、あなたはそれらが変化したときにsomething
を内部オブジェクトのsomethingelse
と合計したいだけです。また、変更がそれらの1つにある場合は、他のすべての内部オブジェクトをループする必要はありません。
_$watch
_がないため、_stuff.property
_は起動していません。また、_stuff.*.something
_のようなパターンもありません。
オブジェクトが配列からプッシュまたはプルされる瞬間がわかっている場合は、オブジェクトを配列に挿入する前後に、個別に$scope.$watch(object, function(){}, true)
を適用できます。この瞬間がわからない場合は、配列全体を_$watch
_する必要があります。変更が発生した場合は、すべての登録解除関数を実行し、それらすべてを1つずつ_$watch
_します。
とにかく、最近のブラウザのループはかなり高速であり、重い計算を行っていて、何百万ものオブジェクトがある場合(すでにメモリの問題であったはずです)を除いて、おそらくそれでうまくいくでしょう。したがって、それらをすべて個別に_$watch
_する努力は、システムのパフォーマンスを構成する可能性のある非常に重い計算がある場合にのみ必要です。