angularjs - 当 $interval 触发时,ng-show 不会更新 class
angularjs - ng-show doesn't update class when $interval triggers
尝试使用 angular 中的 $interval 来使用 ng-show 更改列表中当前可见的项目。检查 html,我注意到 angular 从 true/false 更改了 ng-show,但它没有删除 ng-hide class。
html 很简单:
<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>
app.js 也很基础:
(function(){
var app = angular.module('MyApp', ['my-controller']);
})();
和我的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);
}]);
})();
这是因为您在 ng-show 表达式中使用插值 ({{i == $index}}
) 设置字符串 "true"/"false",而不是直接提供表达式。
ng-show="i == $index"
只是为了补充说明,看看 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
});
});
它在属性值上注册了一个监视,所以当使用插值(首先渲染)时,它实际上为第一个项目设置了监视 "true"
,为最后三个设置了 "false"
(作为预期的)。一切都很好,手表第一次运行以进行脏检查,它被解析为布尔值,并将 ng-hide class 添加到最后 3 个,第一个仍然显示。所以直到现在 watch 设置在范围上的字符串 "true/false" 上并且它永远不会改变并且 watch 不再执行(因为它总是 return 在摘要周期中由超时触发的相同值case) 和 items shows 保持显示状态,hidden 保持隐藏状态,因为它永远没有机会执行 add/removeClass
。现在,当您使用表达式时,每次摘要发生时都会对其进行评估,布尔标志评估为表达式的值发生变化并且观察者被执行并且 class 按预期获得 added/removed。
尝试使用 angular 中的 $interval 来使用 ng-show 更改列表中当前可见的项目。检查 html,我注意到 angular 从 true/false 更改了 ng-show,但它没有删除 ng-hide class。 html 很简单:
<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>
app.js 也很基础:
(function(){
var app = angular.module('MyApp', ['my-controller']);
})();
和我的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);
}]);
})();
这是因为您在 ng-show 表达式中使用插值 ({{i == $index}}
) 设置字符串 "true"/"false",而不是直接提供表达式。
ng-show="i == $index"
只是为了补充说明,看看 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
});
});
它在属性值上注册了一个监视,所以当使用插值(首先渲染)时,它实际上为第一个项目设置了监视 "true"
,为最后三个设置了 "false"
(作为预期的)。一切都很好,手表第一次运行以进行脏检查,它被解析为布尔值,并将 ng-hide class 添加到最后 3 个,第一个仍然显示。所以直到现在 watch 设置在范围上的字符串 "true/false" 上并且它永远不会改变并且 watch 不再执行(因为它总是 return 在摘要周期中由超时触发的相同值case) 和 items shows 保持显示状态,hidden 保持隐藏状态,因为它永远没有机会执行 add/removeClass
。现在,当您使用表达式时,每次摘要发生时都会对其进行评估,布尔标志评估为表达式的值发生变化并且观察者被执行并且 class 按预期获得 added/removed。