jquery 隐藏数千种元素的最快方法< li>?

yb3bgrhw  于 11个月前  发布在  jQuery
关注(0)|答案(8)|浏览(106)

我有一个自动完成表单,用户可以在其中输入一个术语,它隐藏了所有不包含该术语的<li>元素。
我最初使用jQuery的each遍历所有<li>,并将.hide()应用于不包含该术语的那些。
我发现一个更快的方法是遍历所有的<li>,并将类.hidden应用于所有需要隐藏的对象,然后在循环结束时执行$('.hidden').hide()
一个可能更快的方法是使用document.styleSheets重写.hidden类的CSS规则。有人能想到更好的方法吗?
编辑:让我澄清一些我不确定太多人知道的事情。如果你在循环的每次迭代中修改DOM,并且修改导致页面被重绘,这将比“准备”所有修改并在循环结束时一次性应用它们慢得多。

swvgeqrz

swvgeqrz1#

当你处理成千上万的项目时,DOM操作很慢。循环遍历许多DOM元素并根据元素的特征操作每个元素通常不是一个好主意,因为这涉及到在每次迭代中对DOM方法的大量调用。正如你所看到的,它真的很慢。
一个更好的方法是将你的 * 数据 * 与DOM分开。通过JS字符串数组进行搜索要快几个数量级。
这可能意味着将数据集作为JSON对象加载。如果这不是一个选项,您可以循环<li> s一次(在页面加载时),并将数据复制到数组中。
现在你的数据集不依赖于DOM元素的存在,你可以在用户每次输入时使用.html()简单地替换<ul>的整个内容。(这比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个项目。)
为了避免这种情况,我会考虑将显示的结果数量限制在一个合理的数量。(1,000似乎和任何数量一样好。)这是自动完成的;没有人真正查看所有的结果-他们会继续输入,直到结果集对人类来说是可管理的。

ctehm74n

ctehm74n2#

我知道这是一个老问题,但我对任何答案都不满意。目前我正在做一个Youtube项目,它使用了jQuery Selectable list,大约有120.000个条目。这些列表可以通过文本过滤,然后显示相应的条目。隐藏所有不匹配元素的唯一可接受的方法是先隐藏ul元素,而不是隐藏li元素,然后显示列表(ul)。元素中。

dly7yett

dly7yett3#

您可以直接选择所有s,然后过滤它们:$("li").filter(function(){...}).hide()(参见here
(对不起,我之前发错了)

vi4fp9gy

vi4fp9gy4#

你可以使用jQuery contains()选择器来查找列表中包含特定文本的所有项目,然后隐藏它们,就像这样:
超文本标记语言:

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

字符串
jQuery

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

ioekq8ef

ioekq8ef5#

您可以使用一种更独特的技术,在技术上不使用JavaScript来进行实际隐藏,方法是将数据的副本放在属性中,并使用CSS属性选择器。
例如,如果术语是secret,并且您将数据的副本放在data-term属性中,则可以使用以下CSS:

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

字符串
要动态地做到这一点,你必须在JavaScript中为head添加一个样式:

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


如果你要这样做,你会希望确保在停止使用它们时清理样式标记。
这可能是最快的,因为CSS选择在现代浏览器中是非常快的。这将是很难基准,所以我不能肯定,虽然。

wwtsj6pe

wwtsj6pe6#

怎么样:

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

字符串
这样你就不必使用$('. hidden').hide()进行额外的查询了?

xmakbtuz

xmakbtuz7#

你可以直接定义'hide' class属性为“display:none;”,而不是重新定义样式表规则,在你的页面中,你可以在通过JavaScript验证条件后应用你定义的类,如下所示。

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

字符串
以后,如果你想再次显示那些li,你可以像下面这样删除类

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

mf98qq94

mf98qq948#

在新创建的样式表上使用insertRule

// create and append a new stylesheet
const style = document.createElement('style');
document.head.appendChild(style);
// get the sheet part of the stylesheet
const styleSheet = style.sheet;
styleSheet.insertRule('li.hidden{display:none;}');

字符串
我还没有对此进行基准测试,但假设内部浏览器代码可能比JavaScript循环快一点。
我知道你提到了文档。样式表,但这是一个更孤立的方法。

相关问题