控制器函数使用 ng-show 被调用两次 [英] Controller function getting called twice using ng-show
问题描述
我有一个非常简单的 Angular 应用设置,代码如下:
index.html
<头><script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js'></script><script src='app.js'></script>头部><body ng-app="app"><div ng-controller="MyCtrl"><div ng-show="ready()">部分内容
</html>
和app.js
var app = angular.module('app', []);app.controller('MyCtrl', function($scope) {console.log("MyCtrl 被调用")$scope.ready = function() {console.log("准备调用");返回真;}})
如果您在控制台打开的情况下运行此程序,您将看到 MyCtrl 被调用 一次和 ready 被调用 两次.我花了好几个小时试图弄清楚这一点,我看不出为什么 $scope.ready
只会被称为一次.
如果您使用 Angular v1.1.5 并使用 ng-if
而不是 ng-show
,您将具有相同的行为,但如果您使用 ng-init
它正确地调用了 $scope.ready
一次.就我而言,我需要 ng-show
或 ng-if
.
Plunkr:http://plnkr.co/edit/ZSwVNLeFSuhbouXZu9SM?p=preview一个>
说明:为了详细说明我的目标,让我们说 $scope.ready
在某个时候返回 false
(也许它进行了 AJAX 调用,不应该调用更多不止一次),我希望某些内容"不再可见.即基于 $scope.ready
的结果的动态行为.
有什么想法吗?感谢您的帮助!
这是设计使然,而不是错误(并且它与 AngularJS 编译器无关,正如另一个错误陈述的答案).ng-show
和 ng-hide
通过观察"表达式 ready()
的变化来工作.
在每个摘要循环中,对于每个 watch,AngularJS 都会评估相关的表达式以查看是否有任何更改,如果有,则调用侦听器(在 ng-show
/ 的情况下)ng-hide
,监听器将根据 ready()
返回的值显示或隐藏元素.
现在,AngularJS 不能仅仅满足于 ready()
返回的第一个值,因为在同一个摘要周期中,某些东西(例如另一个 watch 表达式)实际上可能会做出一些改变,导致任何ready()
返回一个不同的值(例如,通过改变 ready()
返回的 isReady
变量).显然,开发人员希望将最新值反映到 DOM 中.
因此,AngularJS 将至少评估每个 watch 表达式一次,以确保它在完成摘要循环之前稳定".当然,如果表达式不断变化,这会导致无限的摘要迭代,因此如果摘要循环无法在 10 次迭代内完成,AngularJS 将抛出错误.
I have a very simple Angular app setup, code as follows:
index.html
<!DOCTYPE html>
<html>
<head>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js'></script>
<script src='app.js'></script>
</head>
<body ng-app="app">
<div ng-controller="MyCtrl">
<div ng-show="ready()">
Some content
</div>
</div>
</body>
</html>
And app.js
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
console.log("MyCtrl called")
$scope.ready = function() {
console.log("ready called");
return true;
}
})
If you run this with your console open you will see MyCtrl called once and ready called twice. I have spent hours trying to figure this out, I see no reason why $scope.ready
would be called anything but exactly one time.
If you use a Angular v1.1.5 and use ng-if
instead of ng-show
you will have the same behaviour, but if you use ng-init
it correctly calls $scope.ready
one time. In my case I will need ng-show
or ng-if
.
Plunkr: http://plnkr.co/edit/ZSwVNLeFSuhbouXZu9SM?p=preview
Clarification:
To elaborate on what I'm aiming for, let's say $scope.ready
at some point later returns false
(maybe it makes an AJAX call, that should NOT be called more than once), I would like "Some content" to no longer be visible. That is, dynamic behaviour based on the result of $scope.ready
.
Any ideas? Thank you for the help!
For the record this and this are not the same problem.
This is by design, not a bug (and it has nothing to do with the AngularJS compiler, as another answer incorrectly stated). ng-show
and ng-hide
work by "watching" changes of the expression ready()
.
At each digest cycle, for every watch, AngularJS evaluates the associated expression to see if there's any change and if there is, invoking the listener (in the case of ng-show
/ng-hide
, the listener will show or hide the element based on the value returned by ready()
).
Now, AngularJS can't just be satisfied with the first value returned by ready()
because during the same digest cycle, something (e.g. another watch expression) might actually make some change that causes whatever returned by ready()
to be a different value (e.g. by mutating an isReady
variable which is returned by ready()
). Obviously, developers would expect the latest value to be reflected to the DOM.
Therefore, AngularJS will evaluate every watch expression at least once to make sure that it is "stabilized" before finishing a digest cycle. Of course, this can lead to infinite digest iterations if an expression keeps changing, so AngularJS will throw an error if a digest cycle could not finish within 10 iterations.
这篇关于控制器函数使用 ng-show 被调用两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!