在AngularJS中,我有一个监视范围变量的指令。当变量包含某些数据时,我需要稍微更改该变量。问题是,当我更改变量时,我的$watch
再次被触发。所以我最终会在一个循环中结束。
scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
});
这会再次触发$watch
,这是有道理的。但我确实需要一种方法来改变观察变量。有没有办法做到这一点?
答案 0 :(得分:25)
当使用$scope.$watch
监视变量的变化时,angular会检查参考是否已更改。如果有,则执行$watch
处理程序以更新视图。
如果您计划更改$ watch处理程序中的范围变量,它将触发无限$ digest循环,因为范围变量引用每次调用时都会更改。
解决无限摘要问题的诀窍是使用 angular.copy 保留 $watch
处理程序中的引用(docs):
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
变量不是一个好主意。但是,有时它可能是不可避免的。
答案 1 :(得分:13)
内部函数使用 if 条件以避免连续循环
scope.$watch('someVar', function(newValue, oldValue) {
if(newValue!==oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
}
});
答案 2 :(得分:2)
这是脏检查的工作原理。每当$scope
上的某些内容发生变化时,Angular都会旋转附加到范围内的所有内容,并且它会继续这样做,直到不再有更改。
如果你想做类似的事情,你必须确保你的$watch
功能是幂等的。您必须同时查看newValue
和oldValue
,并确定您已在此$digest
循环中将更改应用于变量。如何做到这一点取决于您对someVar
所做的更改。
一般来说,在监视功能中更改监视变量遗憾的是不是一个好主意。
答案 3 :(得分:2)
您可以使用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];
}
});
答案 4 :(得分:1)
是的,你可以像这样取消它
var wathcer = scope.$watch('someVar', function(newValue, oldValue) {
console.log(newValue);
scope.someVar = [Do something with someVar];
});
wathcer(); // clear the watch