控制器函数使用 ng-show 被调用两次 [英] Controller function getting called twice using ng-show

查看:26
本文介绍了控制器函数使用 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-showng-if.

Plunkr:http://plnkr.co/edit/ZSwVNLeFSuhbouXZu9SM?p=preview

说明:为了详细说明我的目标,让我们说 $scope.ready 在某个时候返回 false (也许它进行了 AJAX 调用,不应该调用更多不止一次),我希望某些内容"不再可见.即基于 $scope.ready 的结果的动态行为.

有什么想法吗?感谢您的帮助!

记录这个不是同一个问题.

解决方案

这是设计使然,而不是错误(并且它与 AngularJS 编译器无关,正如另一个错误陈述的答案).ng-showng-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屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆