angularjs - ng-show 在 $interval 触发时不更新类 [英] angularjs - ng-show doesn't update class when $interval triggers

查看:22
本文介绍了angularjs - ng-show 在 $interval 触发时不更新类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试使用 angular 中的 $interval 来使用 ng-show 更改列表中当前可见的项目.检查 html,我注意到 ng-show 从 true/false 角度更改,但它没有删除 ng-hide 类.html很简单:

你好Plunker!

<div ng-controller="MyCtrl"><div>迭代器:{{i}}</div><ul><li ng-repeat="d in data" ng-show="{{i == $index}}">{{i}} - {{$index}} - {{d}}</里>

app.js 也很基础:

(function(){var app = angular.module('MyApp', ['my-controller']);})();

和我的模块/控制器

(function(){var app = angular.module('我的控制器', []);app.controller('MyCtrl', ['$scope', '$interval', function($scope, $interval){$scope.data = [111, 222, 333, 444];$scope.i = 0;var timeoutId;timeoutId = $interval(function(){$scope.i++;if ($scope.i >= $scope.data.length)$scope.i = 0;},1000);}]);})();

这是我的 plnkr

解决方案

那是因为您使用插值设置字符串 "true"/"false" ({{i == $index}}) 在 ng-show 表达式中,而不是直接提供表达式.

ng-show="i == $index"

Plnkr

只是为了添加解释,看看ng-show 源代码

 scope.$watch(attr.ngShow, function ngShowWatchAction(value) {//我们正在为 ng-hide 添加一个临时的、特定于动画的类,因为这样//我们可以控制元素何时实际显示在屏幕上,而无需//有一个全局/贪婪的 CSS 选择器,当其他动画运行时会中断.//阅读:https://github.com/angular/angular.js/issues/9103#issuecomment-58335845$animate[值?'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {临时类:NG_HIDE_IN_PROGRESS_CLASS});});

它在属性值上注册一个监视,所以当使用插值(首先呈现)时,它实际上将监视设置在 "true" 上的第一项和 "false" 最后三个(正如预期的那样).一切都很好,手表第一次运行进行脏检查,它被解析为布尔值,并将 ng-hide 类添加到最后 3 个,第一个保持显示.所以到目前为止 watch 设置在范围上的字符串true/false"上,它永远不会改变并且 watch 不再执行(因为它总是会在你的情况下超时触发的摘要周期中返回相同的值)和项目显示保持显示,隐藏保持隐藏,因为它永远没有机会执行 add/removeClass.现在,当你使用一个表达式时,它会在每次摘要发生时被评估,布尔标志被评估为表达式的值改变并且观察者被执行并且类被按预期添加/删除.

Trying to use $interval from angular to change the currently visible item in a list using ng-show. Inspecting the html, I noticed that angular changes ng-show from true/false, but it doesn't remove the ng-hide class. The html is simple:

<h1>Hello Plunker!</h1>
<div ng-controller="MyCtrl">
  <div>Iterator: {{i}}</div>
  <ul>
    <li ng-repeat="d in data" ng-show="{{i == $index}}">{{i}} - {{$index}} - {{d}}</li>
  </ul>
</div>

The app.js is quite basic as well:

(function(){  
   var app = angular.module('MyApp', ['my-controller']);
})();

and my module/controller

(function(){
  var app = angular.module('my-controller', []);

  app.controller('MyCtrl', ['$scope', '$interval', function($scope, $interval){
    $scope.data = [111, 222, 333, 444];
    $scope.i = 0;
    var timeoutId;


    timeoutId = $interval(function(){
      $scope.i ++;  
      if ($scope.i >= $scope.data.length)
        $scope.i = 0;
    },
    1000);


  }]);
})();

Here's my plnkr

解决方案

That is because you are setting the string "true"/"false" by using interpolation ({{i == $index}}) in the ng-show expression, instead just provide the expression directly.

ng-show="i == $index"

Plnkr

Just to add explanation, have a look at the ng-show source code

 scope.$watch(attr.ngShow, function ngShowWatchAction(value) {
    // we're adding a temporary, animation-specific class for ng-hide since this way
    // we can control when the element is actually displayed on screen without having
    // to have a global/greedy CSS selector that breaks when other animations are run.
    // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845
    $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
      tempClasses: NG_HIDE_IN_PROGRESS_CLASS
    });
  });

It registers a watch on the attribute value, so when using interpolation (which renders first) so it actually sets watch on "true" for the first item and "false" for the last three (As expected). All is well and the watch runs for the first time for dirty checking and it gets parsed to boolean value and it adds ng-hide class to the last 3 and first one remains displayed. So till now watch is set on the string "true/false" on the scope and it is never going to change and watch no longer executes (since it always will return same value during the digest cycle triggered by timeout in your case) and items shows remains shown and hidden remains hidden as it never gets a chance to execute add/removeClass. Now when you use an expression it will get evaluated every time digest happens, boolean flag evaluated as value of the expression changes and watcher gets executed and class gets added/removed as intended.

这篇关于angularjs - ng-show 在 $interval 触发时不更新类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆