隐藏数千个<li>元素的最快方法
Fastest way to hide thousands of <li> elements?
我有一个自动完成表单,用户可以在其中键入一个术语,它会隐藏所有不包含该术语<li>
元素。
我最初使用 jQuery 的each
遍历所有<li>
,并将.hide()
应用于不包含该术语的。 这太慢了。
我发现一种更快的方法是遍历所有<li>
并将类.hidden
应用于所有需要隐藏的内容,然后在循环结束时执行$('.hidden').hide()
。 不过,这感觉有点黑客。
一种可能更快的方法可能是使用 document.styleSheets
重写 .hidden
类的 CSS 规则。 谁能想到更好的方法?
编辑:让我澄清一些我不确定太多人知道的事情。 如果您在循环的每次迭代中更改 DOM,并且该更改导致页面被重绘,这将比"准备"所有更改并在循环完成后一次应用它们要慢得多。
每当你处理数千个项目时,DOM 操作都会很慢。 循环遍历许多 DOM 元素并根据该元素的特征操作每个元素通常不是一个好主意,因为这涉及在每次迭代中对 DOM 方法的大量调用。 如您所见,它真的很慢。
更好的方法是将数据与 DOM 分开。 搜索 JS 字符串数组的速度要快几个数量级。
这可能意味着将数据集加载为 JSON 对象。 如果这不是一个选项,您可以遍历一次<li>
(在页面加载时),然后将数据复制到数组中。
现在,您的数据集不依赖于存在的 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);
});
如您所见,这非常快。
但是请注意,如果将其增加到 10,000 个项目,则前几次击键的性能开始受到影响。 这与插入到 DOM 中的结果数更相关,而不是与要搜索的原始项数相关。 (随着您键入的内容越多,要显示的结果就越少,性能也很好 - 即使它仍在搜索所有 10,000 个项目。
为了避免这种情况,我会考虑将显示的结果数量限制在一个合理的数字。 (1,000 似乎和任何一样好。 这是自动完成的;没有人真正查看所有结果 - 他们会继续键入,直到结果集对人类来说是可管理的。
这个问题很旧,但我对任何答案都不满意。目前,我正在开发一个使用jQuery Selectable列表的Youtube项目,该项目大约有120.000个项目。这些列表可以按文本过滤,然后显示相应的项目。隐藏所有不匹配元素的唯一可接受的方法是先隐藏 ul 元素,而不是隐藏 li 元素并再次显示 list(ul) 元素。
您可以直接选择所有
$("li").filter(function(){...}).hide()
(见这里)
(对不起,我之前发错了)
您可以使用 jQuery contains() 选择器在包含特定文本的列表中查找所有项目,然后隐藏它们,如下所示:
.HTML:
<ul id="myList">
<li>this</li>
<li>that</li>
<ul>
jQuery
var term = 'this';
$('li:contains("' + term + '")').hide();
您可以使用一种更独特的技术,该技术在技术上不使用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选择在现代浏览器中非常快。这很难进行基准测试,所以我不能肯定地说。
怎么样:
<style>
.hidden{ display: none; }
</style>
这样你就不必使用 $('.hidden').hide() 进行额外的查询?
无需重新定义样式表规则,您可以直接定义"隐藏"类属性到"显示:无;"之前和你的页面中,你可以只应用通过 JavaScript 验证条件后定义的类,如下。
$("li").each(function(){if(condition){$(this).addClass('hide');}});
稍后,如果您想再次显示这些 li,您可以像下面这样删除该类
$("li").each(function(){if(condition){$(this).removeClass('hide');}});
- 完全可链接的li元素
- 使用li元素的html内容更改该元素的背景
- 需要在量角器中找到使用ng中继器的li元素的数量
- 根据输入值创建li元素
- 要更改变量的高度li元素
- 为li元素添加标题
- 在不使用sort()的情况下获取HTML LI元素的副本
- 将内容从 JSON 数组附加到 li 元素
- 获取 LI 元素的偏移宽度(或等效项)
- addClass 到当前 li 元素并删除类
- 使用纯JS点击即可从li元素中获取文本和id
- Rails-使用Ajax删除li元素
- 对具有相同类级别的不同li元素进行排序
- 显示/隐藏具有不同类的li元素
- 从ul中删除li元素
- 从OL中移除LI元素
- 删除不起作用的li元素
- 从javascript生成的li a元素触发onclick
- 如何使用json对象作为li元素的id属性或使用javascript锚定标记id
- 添加和删除jquery-li元素