AngularJSには、スコープ変数を監視するディレクティブがあります。変数に特定のデータが含まれている場合、その変数を少し変更する必要があります。問題は、変数を変更すると$watch
が再びトリガーされます。だから私は連続ループになってしまいます。
scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
});
これにより、$watch
再び、これは理にかなっています。しかし、監視対象の変数を変更する方法が必要です。これを行う方法はありますか?
_$scope.$watch
_を使用して変数の変更を監視する場合、angularは参照が変更されたかどうかを確認します。変更された場合、ビューを更新するために_$watch
_ハンドラーが実行されます。
$ watchハンドラー内でスコープ変数を変更する場合、スコープ変数参照は呼び出されるたびに変わるため、無限の$ digestループがトリガーされます。
無限ダイジェストの問題を回避するためのコツは、angle.copy( docs )を使用して_$watch
_ハンドラー内の参照をpreserveすることです。 :
_scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
var someVar = [Do something with someVar];
// angular copy will preserve the reference of $scope.someVar
// so it will not trigger another digest
angular.copy(someVar, $scope.someVar);
});
_
注:このトリックは、オブジェクト参照に対してのみ機能します。プリミティブでは機能しません。
一般的に、独自の_$watched
_リスナー内で_$watch
_変数を更新することはお勧めできません。ただし、避けられない場合もあります。
関数内でif条件を使用して、連続forループを回避します
scope.$watch('someVar', function(newValue, oldValue) {
if(newValue!==oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
}
});
これがダーティチェックの仕組みです。 $scope
の何かが変更されるたびにAngularはスコープにアタッチされているすべてのものをスピンし、それ以上変更がなくなるまでそうし続けます。
そのようなことをしたい場合は、$watch
関数がべき等であることを確認する必要があります。 newValue
とoldValue
の両方を見て、この$digest
ループで既に変数に変更を適用したかどうかを把握する必要があります。それを行う方法は、someVar
に対してどのような変更を行っているかによって多少異なります。
一般的に、ウォッチ関数でウォッチ変数を変更することは残念ながら良い考えではありません。
bool変数を使用して管理できます
$scope.someVarChanged = false;
scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
$scope.someVarChanged = !$scope.someVarChanged!;
if($scope.someVarChanged) {
scope.someVar = [Do something with someVar];
}
});
はい、このようにキャンセルできます
var wathcer = scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
});
wathcer(); // clear the watch