1

确定容器中是否至少有一个孩子可见的最快方法divdiv什么?

我一直在使用这个:

if ($this.children('div:visible').length) {...

但它很慢,因为它检查了所有的孩子(其中有很多)。

我猜最快的方法将在找到第一个可见元素后立即停止搜索,但最快的方法获胜:)

顺便提一句:

我的实际情况是一个主要容器,其中包含大约 100 个次要容器,每个次要容器最多包含 100 个元素。我想确定哪些次要容器至少有一个可见元素。底部的元素被各种类隐藏和显示。

谢谢。

4

5 回答 5

5

此页面上所有方法的 JSPerf

编辑:我原来的方法更快的原因是它使用.find('>' + selector), where.children()必须使用(循环遍历所有子元素,并检查元素是否与选择器匹配)。

由于div是原生支持的选择器,并且测试用例不包含深度嵌套的元素,因此我的解决方案速度很快。但是在对其进行规范化之后,它看起来几乎等于 qwertymks 解决方案。这两种方案的 JSPerf 会显示他的方案稍微快一点,因为它少了一个函数调用。

此页面上的解决方案是通用的:下面的代码可以针对特定情况进行优化(例如选择器只是一个标签的事实):http: //jsfiddle.net/kFZJs/


为了加快进度,拆分选择器,因为:visible不是原生的 CSS 选择器。

首选的解决方案应该使用尽可能少的 jQuery,因为所需的解决方案必须是高性能的。为此,请检查:visible.

原始函数包含jQuery.support.reliableHiddenOffsets. 当您的孩子不是表格单元格(仅在 IE8- 中使用)时,可以安全地剥离这有利于性能。

现在,编写一个 jQuery 插件(它并不昂贵):

 (function($) {
     $.fn.hasAtLeastOneVisibleChild = function(selector) {
         var $col = this.children(selector), i, elem;
         for (i=0; i<$col.length; i++) {
             var elem = $col[i];
             if (elem.offsetWidth !== 0 || elem.offsetHeight !== 0) {
                 return true;
             }
         }
         return false;
     };
 })(jQuery);
 // Usage:
 $this.hasAtLeastOneVisibleChild('div'); // True or false
于 2012-07-10T11:55:48.917 回答
3

一种方法是使用each()遍历子项。但是,如果可见元素是最后一个元素,这将与您的代码一样慢:)

另一种选择是检查容器的高度。

if($('#container').height() > 0) { ... }

如果孩子占用空间(高度),那么容器的高度也将 > 0。

于 2012-07-10T11:54:11.427 回答
1

试试这个,使用 each 进行迭代并在匹配时返回 false 可能会减少迭代。

isAtleastVisible = false;
$this.children('div').each(function (){
    if($(this).is(':visible') == true)
    {
       isAtleastVisible = true;
       return false;  //This will break each loop at the first visible div
    }
});

if(isAtleastVisible)
   alert("atleast one is visible");
else
   alert("None is visible");

这将提高性能,它取决于可见 div 的第一次出现。如果是百分之一,则只需要一次迭代,如果是百分之一,则需要一百次迭代,并且不会有任何性能提升。

正如@Rob W在回答有关 is('visible') 的工作时解释的那样,该函数通过这些参数检查可见性。

  1. 宽度和高度为零
  2. style.display 没有

假设通过设置 display = none 隐藏元素,您可以使用其中之一来提高性能。这个条件可以用 javascript 语句 .style.display == 'block' 替换 jQuery 方法 .is(':visible') == true

    isAtleastVisible = false;
    $this.children('div').each(function (){
        if(this.style.display == 'block')
        {
           isAtleastVisible = true;
           return false;  //This will break each loop at the first visible div
        }
    });
于 2012-07-10T11:50:46.280 回答
1

自己做:

var $container = $('#container'), $children = $container.children(), found = false;

for (var i = 0; i < $container.length; i++) {
    var elem = $children[i];
    if (!( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none")){
        found = true;
        break;
    }
}

资源

于 2012-07-10T11:54:30.073 回答
0
var isVisible;
$(this.children('div')).each(function() {
    if ($(this).is(":visible")) {
        isVisible = true;
        return false;
    }
});
于 2012-07-10T11:52:16.343 回答