隐藏成千上万个<li>元素的最快方法?</li>

时间:2012-08-12 19:42:58

标签: javascript jquery optimization hide

我有一个自动填充表单,用户可以在其中键入一个术语,并隐藏所有不包含该术语的<li>元素。

我最初使用jQuery <li>遍历所有each并将.hide()应用于不包含该术语的<li>。这太慢了。

我发现更快的方法是遍历所有.hidden并将类$('.hidden').hide()应用于需要隐藏的所有内容,然后在循环结束时执行.hidden。但这有点像黑客。

可能更快的方法是使用document.styleSheets重写{{1}}类的CSS规则。谁能想到更好的方法?

编辑:让我澄清一些我不确定太多人知道​​的事情。如果在循环的每次迭代中更改DOM,并且该更改导致重新绘制页面,那么这将比“准备”所有更改并在循环完成时立即应用它们慢得多。

6 个答案:

答案 0 :(得分:23)

每当你处理成千上万的项目时,DOM操作变慢。循环遍历许多DOM元素并基于该元素的特性操纵每个元素通常不是一个好主意,因为这涉及在每次迭代中对DOM方法的大量调用。如你所见,它真的很慢。

更好的方法是将数据与DOM分开。搜索JS字符串数组要快几个数量级。

这可能意味着将数据集加载为JSON对象。如果这不是一个选项,您可以遍历<li>一次(在页面加载时),并将数据复制到一个数组中。

现在您的数据集不依赖于存在的DOM元素,您可以在每次用户键入时使用<ul>替换.html()的全部内容。 (这比JS DOM操作快得多,因为当您只是更改innerHTML时,浏览器可以优化DOM更改。)

var dataset = ['term 1', 'term 2', 'something else', ... ];

$('input').keyup(function() {
    var i, o = '', q = $(this).val();
    for (i = 0; i < dataset.length; i++) {
        if (dataset[i].indexOf(q) >= 0) o+='<li>' + dataset[i] + '</li>';
    }
    $('ul').html(o);
});

As you can see,这非常快。


但请注意,如果你up it to 10,000 items,性能开始受到前几次击键的影响。这与插入到DOM中的结果数量相关,而不是与搜索的原始数量相关。 (当您输入更多内容并且显示的结果较少时,性能很好 - 即使它仍在搜索所有10,000个项目。)

为避免这种情况,我会考虑将显示的结果数量限制为合理的数字。 (1000似乎和任何一样好。)这是自动完成的;没有人真正查看所有结果 - 他们将继续输入,直到结果集对人类可管理。

答案 1 :(得分:1)

您可以直接选择所有&lt; li&gt; s,然后对其进行过滤:$("li").filter(function(){...}).hide()(请参阅here

(抱歉,我以前发错了)

答案 2 :(得分:1)

您可以使用jQuery contains()选择器查找列表中包含特定文本的所有项目,然后隐藏它们,如下所示:

HTML:

 <ul id="myList">
      <li>this</li>
      <li>that</li>
 <ul>​

的jQuery

var term = 'this';    
$('li:contains("' + term + '")').hide();​

答案 3 :(得分:0)

怎么样:

<style>
    .hidden{ display: none; }
</style>

这样你就不必使用$(&#39; .hidden&#39;)来进行额外的查询.hide()?

答案 4 :(得分:0)

您可以直接定义“隐藏”,而不是重新定义样式表规则 class属性为“display:none;”在手和你的页面之前,你可以 在通过javascript验证条件后应用您定义的类, 如下。

$("li").each(function(){if(condition){$(this).addClass('hide');}});

以后,如果你想再次显示那些li,你可以删除下面的类

$("li").each(function(){if(condition){$(this).removeClass('hide');}});

答案 5 :(得分:0)

您可以使用更独特的技术,在技术上不使用JavaScript来执行实际隐藏,方法是将数据的副本放在属性中,并使用CSS属性选择器。

例如,如果术语为secret,并且您将数据的副本放在data-term属性中,则可以使用以下CSS:

li[data-term*="secret"] {
    display: none;
}

要动态执行此操作,您必须在javascript中添加样式到头部:

function hideTerm(term) {
    css = 'li[data-term*="'+term+'"]{display:none;}'
    style = $('<style type="text/css">').text(css)
    $('head').append(style);
}

如果你这样做,你可能希望在停止使用它们时清理样式标签。

这可能是最快的,因为在现代浏览器中CSS选择非常快。我很难确定基准,所以我不能肯定地说。