【问题标题】:Why is this simple AngularJS ng-show not working?为什么这个简单的 AngularJS ng-show 不起作用?
【发布时间】:2014-05-17 20:43:35
【问题描述】:

我无法弄清楚为什么我的简单 AngularJS 应用程序无法按预期工作。 “正在加载...”应该被隐藏,“完成!”应在 1 秒后显示。

html:

<div ng-app>
    <div ng-controller="TestCtrl">
        <div class="text-center" ng-show="loading">
            <h1>Loading...</h1>

    </div>
        <div class="text-center" ng-show="!loading">
            <h1>Done!</h1>

        </div>
    </div>
</div>

Javascript:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.loading = false;
    }, 1000);
}

【问题讨论】:

  • 这篇文章很有帮助,但标题不适合谷歌搜索。

标签: javascript angularjs ng-show


【解决方案1】:

你需要告诉 Angular 你更新了 var:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.$apply(function(){
            $scope.loading = false;
        });
    }, 1000);
}

或者只是

function TestCtrl($scope, $timeout) {
    $scope.loading = true;
    $timeout(function () {
        $scope.loading = false;
    }, 1000);
}

【讨论】:

  • 好的,谢谢,刚开始接触AngularJS,不知道apply。谢谢您的帮助。我选择了这个答案 - 因为在我的真实应用程序(不是 jsfiddle)中,StarsSky 使用 $scope.apply() 的方法出现错误。
  • StarSky 的回答出现错误,因为 $timeout 启动了一个摘要周期,而 $apply 正在尝试启动第二个周期,但您不能有超过 1 个摘要在时间。
  • 这是正确的做法,但为什么呢?如果我用新值更新 $scope ,那 $scope 属性不是已经在 $watch 列表中,并且应该通过双向绑定的魔力自动更新 DOM 吗?不明白为什么需要 $scope.$apply()。
  • @darktideac .apply() 不是函数,它是 $apply()。
  • 使用 $q.defer();返回的对象允许您在异步方法完成后调用 .resolve() 或 .reject() 方法。 $q.defer() 对象的 resolve 和 reject 方法都在解析异步方法后在内部调用 $digest。 $digest 告诉 Angular 重新评估您的 $scope 属性,这将满足您的需求。这是一个更好的做法。如果您不需要调用 $apply() 并且有更好的内置角度机制来解决这个问题,请避免调用。
【解决方案2】:

一个更好的方法是调用$scope.$digest(); 来更新你的用户界面

【讨论】:

  • 我不喜欢这个“技巧”,但对我有用(我的 $scope var 已更新为库回调)。谢谢!
  • @user2553863:我不喜欢它,因为框架不应该需要开发人员通知它何时更新 UI,但是 AngularJS有时会。 Angular 2+ 不再有这个问题了。
  • @dbautistav,你说得对,它很烦人,而且增加了复杂性。谢谢!
【解决方案3】:

您需要使用$timeout 并将其注入您的控制器:

function TestCtrl($scope, $timeout) {
    $scope.loading = true;
    $timeout(function () {
        $scope.loading = false;
    }, 1000);
}

Fiddle demo

编辑: 按照@Salman 的建议删除了$scope.apply();

【讨论】:

  • 如果你已经在使用 $timeout 那么没有必要使用 $scope.apply();因为角度确保使用 apply 更新值。
  • $apply(),不是 .apply()
【解决方案4】:

您想使用apply() 函数来停止加载消息。

检查此Demo jsFiddle**。

JavaScript:

function TestCtrl($scope) {
    $scope.loading = true;
    setTimeout(function () {
        $scope.$apply(function(){
            $scope.loading = false;
        });
    }, 1000);
}

希望对你有所帮助!

【讨论】:

    【解决方案5】:

    当向另一个对象(如 setTimeout)触发角度事件时,您应该使用

    $scope.$apply(function(){
         $scope.loading = false;
    });
    

    例如

    var loading={
         show:function(){
            $scope.loading=true
         },
         hide:function(){
            $scope.loading=false
         }
    }  
    

    可能不是最好的方式

       var loading={
             show:function(){
                $scope.$apply(function(){
                   $scope.loading=true
                });
             },
             hide:function(){
                $scope.$apply(function(){
                   $scope.loading=false
                });
             }
        } 
    

    【讨论】:

      【解决方案6】:

      我发现解决 ng-show 未按照您希望的方式进行评估的一种方法是改用 ng-class。

       <div class="mycontent" data-ng-class="{'loaded': !loading}"> 
      

      这样,当 $scope.loading 不等于 true 时,css 类 'loaded' 将被添加到元素中。 然后你只需要使用 css 类来显示/隐藏内容。

      .mycontent {
          display: none;
      }
      
      .loaded {
          display: block;
      }
      

      【讨论】:

        【解决方案7】:

        我认为这里最大的问题是您使用原始模型作为模型。 Angular 团队建议使用一个对象将您的模型绑定到。例如:

        scope.model = {};
        scope.model.loading = false;
        

        然后在你的 html 中:

        <div class="text-center" ng-show="model.loading">
        

        这样,angular 获取对对象内部字段的引用,而不是由变量指向的基元。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-10-18
          • 1970-01-01
          • 2013-10-20
          • 2015-06-29
          • 1970-01-01
          • 2011-10-25
          • 2012-06-25
          相关资源
          最近更新 更多