我使用jquery和javascript的混合来搜索一堆项目。确切地说是5000+。我在我的网站上使用实时搜索功能,根据关键字过滤这些项目。但是因为有很多项目要搜索它,所以我想加快这个过程。
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/JavaScript">
$(document).ready(function() {
$("#filter").keyup(function() {
// Retrieve the input field text and reset the count to zero
var filter = $(this).val(), count = 0;
// Loop through the list
$(".inventory tr").each(function() {
// If the list item does not contain the text phrase fade it out
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
// Show the list item if the phrase matches and increase the count by 1
} else {
$(this).show();
count++;
}
});
// Update the count
var numberItems = count;
$("#filter-count").text("Number of items = "+count);
});
});
</script>
<form id="live-search" action="" class="styled" method="post">
<fieldset>
<input type="text" class="text-input" id="filter" value="" />
<span id="filter-count"></span>
</fieldset>
</form>
<div class="inventory">
<table> Stuff </table>
</div>
我能做些什么来加快速度吗?我非常喜欢这个功能,如果可能的话,我希望将它保留在网站上。
答案 0 :(得分:3)
jQuery比vanilla慢;它的好处是跨浏览器 支持,但你不需要循环这样的东西 对象
你在循环中创建了相同的正则表达式模式 每次迭代;在外面宣布一次
将表的副本保存在内存中并在那里搜索会更快,而不是每次都遍历DOM。也就是说,将数据保存在多维数组中并进行扫描;然后更新表格视图
已经有一个jQuery插件可以为您执行此操作,名为dataTables
答案 1 :(得分:2)
这个小小的非jquery婴儿在大约50毫秒内解析了10000多个元素。
function foo(){
var nodes = document.evaluate('//table[@class="inventory"]//tr', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null),
filterValue = document.getElementById('filter').value;
if (nodes != null && filterValue != '') {
var re = new RegExp(filterValue, "i"), count = 0;
for (var m = 0; m < nodes.snapshotLength; m++){
var item = nodes.snapshotItem(m);
if(re.test(item.innerHTML.replace(/<(?:.|\n)*?>/gm, '').trim())){
count++;
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
}
console.log("Parsed " + nodes.snapshotLength + " elements and matched " + count);
}
function time_my_script(script) {
var start = new Date();
script();
return new Date() - start;
}
window.onload = function() {
var filter = document.getElementById('filter');
filter.onkeyup=function(){ console.log("Time: " + time_my_script(foo) + "ms");}
}
Html
<html>
<head>
<script type="text/javascript">
// ...
</script>
</head>
<body>
<input type="text" id="filter" name="filter" />
<table class="inventory">
<tr>
<td>axxxasd</td>
</tr>
</table>
<table class="inventory">
<tr>
<td>axxxasd</td>
</tr>
</table>
<table class="inventory">
<tr>
<td>axxxasd</td>
</tr>
</table>
<table class="inventory">
<tr>
<td>asd</td>
</tr>
</table>
<!-- ... -->
</body>
</html>
答案 2 :(得分:1)
您可能需要debounce搜索方法:
答案 3 :(得分:1)
我毫不怀疑您的代码目前很慢,您的搜索算法会广泛使用DOM。在键盘上的每个键上,您从选择器中检索节点列表,这是一个非常糟糕的主意,您不应该在Web应用程序中多次检索对DOM节点的引用。
您应该在javascript对象中存储要在DOM之外搜索的数据,并且您可能还需要使用下划线的限制来限制搜索函数的调用率。
请参阅:http://underscorejs.org/#throttle,如果不使用下划线,可以从源代码中提取函数。
答案 4 :(得分:0)
为什么不使用jQuery的内置包含函数?我用它而且速度很快。我使用了一个不区分大小写的contains函数版本。
$(document).ready(function () {
// to make :contains case insensitive!!!
$.expr[":"].contains = $.expr.createPseudo(function (arg) {
return function (elem) {
return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
};
});
$('#filter').on('input', function () {
var $t = $(this);
if ($t.val()) {
$('.inventory tr').hide();
$('.inventory').find('tr:Contains("' + $t.val() + '")').show();
}
else {
$(".inventory tr").show();
}
$("#filter-count").text("Number of items = " + $(".inventory tr:visible").length);
});
});
答案 5 :(得分:0)
我能够将处理时间缩短一半,在某些情况下远远超过这个时间。我正在使用window.performance.now()来测试时间。在Chrome中,您的脚本大部分时间都在140毫秒左右。最长的病例是1400毫秒。下面的脚本运行在50ms-70ms左右,搜索短语看起来越长,脚本越快(低至10ms)。让我知道你的想法(我把循环填满测试数据):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/JavaScript">
$(document).ready(function(){
var startTime;
var endTime;
var i;
var htmlString = "";
for(i = 0; i < 5000; i += 1){
htmlString += "<tr class='inventory'><td>This is my test thing</td></tr>";
}
$('#myTable').html(htmlString);
$("#filter").keyup(function(){
startTime = window.performance.now();
// Retrieve the input field text and reset the count to zero
var filter = $(this).val(),
count = 0,
matchedItems = $('tr.inventory td:contains("'+filter+'")'),
nonMatchedItems = $('tr.inventory td').not(matchedItems),
numItems = matchedItems.length;
matchedItems.show();
nonMatchedItems.hide();
$("#filter-count").text("Number of items = "+numItems);
endTime = window.performance.now();
console.log(endTime - startTime);
});
});
</script>
<form id="live-search" action="" class="styled" method="post">
<fieldset>
<input type="text" class="text-input" id="filter" value="" />
<span id="filter-count"></span>
</fieldset>
</form>
<div class="inventory">
<table id="myTable"></table></div>
</body>
</html>