【问题标题】:Why doesn't Angular update the ng-show status when I use an expression?当我使用表达式时,为什么 Angular 不更新 ng-show 状态?
【发布时间】:2014-09-19 19:45:38
【问题描述】:

当我使用作用域变量时,让 ng-show 工作没有问题:

(摘自html文件:)

<li ng-show="hasBattery">
  <span>Battery</span>
  <dl>
    <dt>Type</dt>
    <dd>{{phone.battery.type}}</dd>
  </dl>
</li>

使用以下控制器代码,效果很好:

phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
  function($scope, $routeParams, $http) {

    function loadData() {
      // fyi, the ?date nonsense below is to avoid browser cacheing of the json file 
      $http.get('phones/' + $routeParams.phoneId + '.json' + '?' + 
                new Date().getTime()).success(function(data) {
        $scope.phone = data; 
        $scope.hasBattery = !$scope.isEmpty($scope.phone.battery.type);
        // should i call some form of $scope.$apply() here? when i do,
        // i get a digest already in progress error. ng-show seems to 
        // update fine without a call to $apply
      });
    };

    $scope.isEmpty = function(str) {
      var retVal = (typeof(str) === undefined || !str || 0 === str.length);
      alert("isempty: returning " + retVal);
      return retVal;
    };

    $scope.hasBattery = false;
    loadData();
  }
]);

就像我说的,这行得通。当我查看 phone.battery.type 未定义或空白的页面时,ng-show 正确隐藏了 div。当我查看 phone.battery.type 是非空字符串的页面时,ng-show 正确显示了 div。都好。

这是我的问题:当我直接在 ng-show 表达式中使用 !isEmpty(...) 调用,而不是使用 $scope.hasBattery 作为中介时,它不会不行。

这是我的那个版本的代码:

<li ng-show="{{!isEmpty(phone.battery.type)}}">
  <span>Battery</span>
  <dl>
    <dt>Type</dt>
    <dd>{{phone.battery.type}}</dd>
  </dl>
</li>

控制器,已移除 hasBattery:

phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
  function($scope, $routeParams, $http) {

    function loadData() {
      $http.get('phones/' + $routeParams.phoneId + '.json' + '?' + new Date().getTime()).success(function(data) {
        $scope.phone = data; 
        // no longer do any evaluation of isEmpty here.
        // as before, I'm not calling $scope.$apply() at all
      });
    };

    // same code as before
    $scope.isEmpty = function(str) {
      var retVal = (typeof(str) === undefined || !str || 0 === str.length);
      alert("isempty: returning " + retVal);
      return retVal;
    };

    loadData();
  }
]);

当我加载一个 phone.battery.type 是非空字符串的页面时,我希望 ng-show 显示它,但它无法显示 div。我看到 isEmpty 确实在数据加载后被调用,并且正确返回 false(因此 ng-show 的表达式 !isEmpty(...) 为 true)。但似乎 Angular 对这个表达式的值没有做任何事情!

.

知道发生了什么吗?我认为这是一个 $scope.$apply 问题,就像我在 SO 的其他地方看到的那样,但似乎确实正在使用最新数据评估表达式。

【问题讨论】:

  • 为什么要用 {{ }} 作为表达式?
  • 我对 Angular 没有太多经验,但不应该是 &lt;li ng-show="!isEmpty(phone.battery.type)"&gt; 而不是 &lt;li ng-show="{{!isEmpty(phone.battery.type)}}"&gt;
  • 当您使用 {{}} 评估 ng-show/ng-if 等内部的表达式时,它只会被评估一次。
  • @Razah - 不要这么认为。见:whitneyland.com/2013/02/…
  • @Mohammad 但我看到警报至少调用了两次。最后一次调用它时,isEmpty 返回 false。那么不应该使用那个返回值吗?然而 ng-show 不显示 div。

标签: javascript angularjs angularjs-scope ng-show angularjs-ng-show


【解决方案1】:

似乎 {{ }} 表示法意味着 Angular 只评估和使用括号内的表达式一次。

听起来要么 Angular 在去年左右改变了它对大括号的处理,要么我一直使用的这个博客条目是错误的:http://www.whitneyland.com/2013/02/why-does-angularjs-sometimes-use-single-braces-sometimes-double-braces-and-sometimes-no-braces.html

评论者 Cyril DD、Razah 和 Mohammad Sepahvand,感谢您指出删除 {{ }} 解决了我的问题。

我仍然很惊讶 Angular 似乎不止一次地评估这个表达式——事实上,很多次,作为 12 次左右的证据我必须解除从 isEmpty 调用的 alert() !

为什么 Angular 会评估一个它知道它不会做任何事情的表达式?

【讨论】:

  • 不用等待,{{ }} 可以被计算多次——例如,绑定变量,如docs.angularjs.org/tutorial/step_09 中演示的——但在角度指令字符串中,就像 ng-show="...",它只会被使用一次。或者至少这是我收集的,仍然希望我能找到一些指南,让这些东西更清晰!
猜你喜欢
  • 1970-01-01
  • 2015-03-14
  • 2014-01-02
  • 1970-01-01
  • 2017-01-29
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多