我有以下代码:
<div ng-hide="items.length == 0">
<li ng-repeat="item in items" ng-hide="item.hide == true">
{{ item.name }} <hide-button />
</li>
</div>
想象一下,我有10件物品。当我单击按钮时,我将item.hide设置为true,项目消失。当我隐藏所有10个项目时,我想隐藏主要div。使用AngularJS实现这一目标的最佳方法是什么?
答案 0 :(得分:5)
一种方法可能是使用这样的函数:
$scope.checkItems = function () {
var total = $scope.items.length;
for (var i = 0; i < $scope.items.length; ++i) {
if ($scope.items[i].hide) total--;
}
return total === 0;
};
并更改外部div上的 ngHide 属性:
ng-hide="checkItems()"
jsfiddle :http://jsfiddle.net/u6vkf6bt/
另一种方法是声明一个$scope.allHidden
变量并监视数组:
$scope.$watch('items', function (newItems) {
var all = true;
for (var i = 0; i < newItems.length; ++i) {
if (newItems[i].hide !== true) all = false;
}
$scope.allHidden = all;
}, true);
这是检查数组中的任何内容何时更改,并检查是否所有hide属性都设置为true。
然后在 ngHide 属性上设置它:
ng-hide="allHidden"
jsfiddle :http://jsfiddle.net/u6vkf6bt/1/
在这两者中,我会选择第一种方法,因为深度观察可能会导致性能问题:
因此,这意味着观看复杂的物体会产生不利影响 记忆和表现的影响。
当$watch(watchExpression, listener, [objectEquality]);
设置为true时objectEquality
下的here。
答案 1 :(得分:1)
另一种方法是在隐藏单个项目时更新隐藏项目的计数器。当然,这需要将隐藏代码放在您的控制器中,如下所示:
$scope.allHidden = false;
// if items can have hide = true property set already from the start
var hiddenItems = $scope.items.filter(function (item) {
return item.hide;
}).length;
// or if they are all initially visible, a straightforward approach:
// var hiddenItems = 0;
$scope.hideItem = function (item) {
item.hide = true;
hiddenItems++;
if (hiddenItems === $scope.items.length) {
$scope.allHidden = true;
}
}
隐藏将需要这样做:
<li ng-repeat="item in items" ng-hide="item.hide == true">{{ item.name }}
<button ng-click="hideItem(item)">hide</button>
</li>
jsfiddle :https://jsfiddle.net/723kmyou/1/
这种方法的优点
这种方法的缺点
答案 2 :(得分:1)
我不喜欢其他解决方案的几个原因:
我首选的解决方案是实际查找第一个可见项: http://plnkr.co/edit/FJv0aRyLrngXJWNw7nJC?p=preview
angular.module('MyApp',[]);
angular.module('MyApp').directive('myParent', function(){
return {
restrict: 'A',
link:function(scope, element){
scope.$watch(function(){
return element.find('>:visible:first').length > 0;
}, function( visible ){
if ( visible ){
element.show();
}else{
element.hide();
}
})
}
}
});
<div my-parent>
<div class="hidden">one child</div>
<div class="hidden">another child</div>
</div>
<div my-parent>
<div class="hidden">third child</div>
<div>another child</div>
</div>
您甚至可以通过将选择器传递给要在指令中使用的“my-parent”属性来扩展它。允许更好地指定要查找的项目。
我喜欢这种方法,因为它几乎没有任何假设。
这可以用于可能隐藏子项的任何场景。不一定是ng-repeat
。
但是,当我们使用:visible
选择器时,手表可能会很昂贵。
另一个 - 假设涉及ng-repeat - 是观察范围的价值 - http://plnkr.co/edit/ZPVm787tWwx9nbJTNg1A?p=preview
app.directive('myParent', function(){
return{
restrict: 'A',
link: function(scope, element,attrs){
scope.$watch(function(){
try{
value = scope.$eval(attrs.myParent);
var i = value.length-1;
for ( ; i >= 0; i-- ){
if ( value[i].hide != false ){
return true;
}
}
}catch(e){
return false
}
return false;
}, function( newValue ){
if ( !!newValue ) { element.show(); } else { element.hide();}
})
}
}});
<ul my-parent="awesomeThings">
<li ng-repeat="thing in awesomeThings">{{thing.value}}</li>
</ul>
这里的手表可能成本较低,不太确定,但它不能处理dom,所以这很有可能......
虽然这与其他解决方案非常相似,但它是作为一个高度可重复使用的指令实现的,并且会查找第一个可见项。
在我的解决方案中,我也假设jquery可用。 如果需要,还有许多其他方法可以实现此目的: AngularJS: element.show() in directive not working
关于watch
表现,不确定哪种方式更好。我正在使用一个函数来评估观察值,我不确定这是否是处理它的最佳方法。