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

Nic*_*ick 11 javascript optimization jquery hide

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

我最初<li>用jQuery 循环遍历所有each并且应用于.hide()那些不包含该术语的那些.这太慢了.

我发现更快的方法是遍历所有<li>并将类.hidden应用于所有需要隐藏的类,然后在循环结束时执行$('.hidden').hide().虽然这感觉有点迟钝.

一个潜在的更快的方法可能是改写了的CSS规则.hidden使用类document.styleSheets.谁能想到更好的方法?

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

jos*_*736 23

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

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

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

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

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);
});
Run Code Online (Sandbox Code Playgroud)

如您所见,这非常快.


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

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