jQuery:确定容器中至少有一个子项是否可见的最快方法

时间:2012-07-10 11:47:12

标签: javascript jquery performance visible

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

我一直在用这个:

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

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

我猜最快的方法会在找到第一个可见元素后立即停止搜索,但无论什么是最快的胜利:)

顺便说一句:

  

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

感谢。

5 个答案:

答案 0 :(得分:5)

此页面上所有方法的JSPerf

已修改我原始方法更快的原因是它使用了.find('>' + selector),其中必须使用.children()(循环遍历所有子节点,并检查是否元素匹配选择器)。

由于div是本机支持的选择器,并且测试用例不包含深层嵌套元素,因此我的解决方案变得很快。但在规范化之后,它看起来几乎等于qwertymks解决方案。这两个解决方案的JSPerf将显示他的解决方案稍微快一些,因为它只有少一个函数调用。

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


要加快进度,请拆分选择器,因为:visible不是本机CSS选择器。

首选解决方案应使用尽可能少的jQuery,因为所需的解决方案必须具有高性能。为此,examine the logic of :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

答案 1 :(得分:3)

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

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

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

如果孩子占用空间(高度),那么容器将具有高度&gt; 0也是。

答案 2 :(得分: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。如果它是第一个中的一个,则仅需要一次迭代,如果它是百分之一百,那么将需要百次迭代并且不会有任何性能增加。

as @Rob W 在回答中解释了is('visible')的工作情况,该函数显示该函数通过这些参数检查可见性。

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

        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
            }
        });
    

答案 3 :(得分:1)

自己动手: {{3H2>

答案 4 :(得分:0)

var isVisible;
$(this.children('div')).each(function() {
    if ($(this).is(":visible")) {
        isVisible = true;
        return false;
    }
});