$watch 没有像预期的那样触发多次
$watch not firing as many times as expected
如果您更改它正在监视的变量 x
次,我希望 $watch
触发 x
次。在我放在一起的一个小例子中,我改变了变量 $scope.foo
的值 3 次,但是关联的 $watch
只运行一次......
<html>
<head>
<title></title>
<script src="https://code.angularjs.org/1.3.8/angular.js"></script>
</head>
<body ng-app='myApp'>
<div ng-controller='MyCtrl'></div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.$watch('foo', function(oldVal, newVal) {
console.log(oldVal, newVal);
});
$scope.foo = "foo";
$scope.foo = "bar";
$scope.foo = "baz";
});
</script>
</body>
</html>
谁能解释这是什么原因,或者我可以采取不同的方法来获得预期的结果?
我期待以下控制台输出:
undefined foo
foo bar
bar baz
但是得到...
baz baz
编辑:另一个例子
myApp.controller('MyCtrl', function($scope, $timeout) {
$scope.$watch('foo', function() {
$scope.bar = 'bar';
});
$scope.foo = "foo";
// now the value of $scope.foo has changed, I was expecting the $watch to have run at this point.
// Apparently is has not because $scope.bar is still undefined. Accessing $scope.bar in a $timeout works, but is there a better way?
console.log($scope.bar)
});
angular 的变化太快了,$timeout
有效:
<html>
<head>
<title></title>
<script src="https://code.angularjs.org/1.3.8/angular.js"></script>
</head>
<body ng-app='myApp'>
<div ng-controller='MyCtrl'></div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope, $timeout) {
$scope.$watch('foo', function(oldVal, newVal) {
console.log(oldVal, newVal);
});
$scope.foo = "foo";
$scope.foo = "bar";
$scope.foo = "baz";
$timeout(function(){
$scope.foo = "foo";
},0)
$timeout(function(){
$scope.foo = "bar";
},0)
$timeout(function(){
$scope.foo = "baz";
},0)
});
</script>
</body>
</html>
见How does AngularJS's $watch function work?
A $watch
只会在每个 angular $digest 周期中触发一次! (如果观看 属性 那是最简单的场景)。
您对 foo
所做的三项更改都发生在同一周期内。而angular会比较循环前后的值。
对于您的情况,您需要通过例如更改 $timeout
.
中的值来触发新循环
编辑
对于您的示例,您可以这样做
myApp.controller('MyCtrl', function($scope) {
$scope.foo = "foo";
// run on controller init
fooWatch();
// watch for changes
$scope.$watch('foo', fooWatch);
function fooWatch() {
$scope.bar = 'bar';
}
});
因为 $digest
循环不是 运行 每次您更改范围内的变量(幸运的是)。
但是当你使用$timeout
时它会被触发。
你的用例是什么?
顺便说一句,在控制器中使用 $watch
通常不是一个好习惯,而且很容易避免。
如果您更改它正在监视的变量 x
次,我希望 $watch
触发 x
次。在我放在一起的一个小例子中,我改变了变量 $scope.foo
的值 3 次,但是关联的 $watch
只运行一次......
<html>
<head>
<title></title>
<script src="https://code.angularjs.org/1.3.8/angular.js"></script>
</head>
<body ng-app='myApp'>
<div ng-controller='MyCtrl'></div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.$watch('foo', function(oldVal, newVal) {
console.log(oldVal, newVal);
});
$scope.foo = "foo";
$scope.foo = "bar";
$scope.foo = "baz";
});
</script>
</body>
</html>
谁能解释这是什么原因,或者我可以采取不同的方法来获得预期的结果?
我期待以下控制台输出:
undefined foo
foo bar
bar baz
但是得到...
baz baz
编辑:另一个例子
myApp.controller('MyCtrl', function($scope, $timeout) {
$scope.$watch('foo', function() {
$scope.bar = 'bar';
});
$scope.foo = "foo";
// now the value of $scope.foo has changed, I was expecting the $watch to have run at this point.
// Apparently is has not because $scope.bar is still undefined. Accessing $scope.bar in a $timeout works, but is there a better way?
console.log($scope.bar)
});
angular 的变化太快了,$timeout
有效:
<html>
<head>
<title></title>
<script src="https://code.angularjs.org/1.3.8/angular.js"></script>
</head>
<body ng-app='myApp'>
<div ng-controller='MyCtrl'></div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope, $timeout) {
$scope.$watch('foo', function(oldVal, newVal) {
console.log(oldVal, newVal);
});
$scope.foo = "foo";
$scope.foo = "bar";
$scope.foo = "baz";
$timeout(function(){
$scope.foo = "foo";
},0)
$timeout(function(){
$scope.foo = "bar";
},0)
$timeout(function(){
$scope.foo = "baz";
},0)
});
</script>
</body>
</html>
见How does AngularJS's $watch function work?
A $watch
只会在每个 angular $digest 周期中触发一次! (如果观看 属性 那是最简单的场景)。
您对 foo
所做的三项更改都发生在同一周期内。而angular会比较循环前后的值。
对于您的情况,您需要通过例如更改 $timeout
.
编辑
对于您的示例,您可以这样做
myApp.controller('MyCtrl', function($scope) {
$scope.foo = "foo";
// run on controller init
fooWatch();
// watch for changes
$scope.$watch('foo', fooWatch);
function fooWatch() {
$scope.bar = 'bar';
}
});
因为 $digest
循环不是 运行 每次您更改范围内的变量(幸运的是)。
但是当你使用$timeout
时它会被触发。
你的用例是什么?
顺便说一句,在控制器中使用 $watch
通常不是一个好习惯,而且很容易避免。