使用 JavaScript 在记录列表中快速过滤
Fast filter in a list of records with JavaScript
我在网页上有一个包含大约 10 000 个客户的列表,需要能够在此列表中搜索匹配的输入。它有一些延迟,我正在寻找提高性能的方法。这是我使用的 HTML 和 JavaScript 的简化示例:
<input id="filter" type="text" />
<input id="search" type="button" value="Search" />
<div id="customers">
<div class='customer-wrapper'>
<div class='customer-info'>
...
</div>
</div>
...
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#search").on("click", function() {
var filter = $("#filter").val().trim().toLowerCase();
FilterCustomers(filter);
});
});
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-wrapper").show();
return;
}
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).parent().show();
} else {
$(this).parent().hide();
}
});
}
</script>
问题是,当我点击“搜索”按钮时,有很长的延迟,直到我得到包含匹配结果的列表。有没有更好的方法来过滤列表?
问题是你正在迭代记录,如果有 10000 条记录,它可能会很慢,所以我的建议是稍微改变结构,这样你就不必迭代了:
在 customer-wrapper
上定义列表的所有 css 特征
class 并使其成为所有列表元素的 父级 div.
当您的 ajax 请求添加一个元素时,创建一个包含名称的变量来替换下划线的空格,我们称之为 underscore_name
.
将名称添加到列表中:
var customerHtml = "<div id='"+underscore_name+'>" + name + "</div>";
列表中的每个元素都有一个与名称"almost"相同的唯一 ID,并且列表中的所有元素都在 同一级别 在 customer-wrapper
class.
下
- 对于搜索,您可以将用户输入的空格替换为下划线并放入变量中,例如
searchable_id
,然后使用 Jquery:
$('#'+searchable_id).siblings().hide()
;
siblings
将隐藏与 searchable_id.
同一级别的其他元素
它可能遇到的唯一问题是出现两个或更多重复名称的情况,因为它会尝试创建两个或更多具有相同 ID 的 div。
您可以在 http://jsfiddle.net/mqpsppxm/ 上查看一个简单的实现
感谢您的所有回答和评论,我至少得到了令人满意的性能结果的解决方案。我已经清理了多余的包装器并将列表中的元素 showing/hiding 分组,而不是对每个元素单独进行。下面是过滤现在的样子:
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-info").show();
} else {
$(".customer-info").hide();
$(".customer-info").removeClass("visible");
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).addClass("visible");
}
});
$(".customer-info.visible").show();
}
}
1) DOM 操作通常很慢,尤其是当您追加新元素时。将所有 html 放入一个变量中并附加它,这会导致一个 DOM 操作并且比对每个元素
快得多
function LoadCustomers() {
var count = 10000;
var customerHtml = "";
for (var i = 0; i < count; i++) {
var name = GetRandomName() + " " + GetRandomName();
customerHtml += "<div class='customer-info'>" + name + "</div>";
}
$("#customers").append(customerHtml);
}
2) jQuery.each() 很慢,请改用 for
循环
function FilterCustomers(filter) {
var customers = $('.customer-info').get();
var length = customers.length;
var customer = null;
var i = 0;
var applyFilter = false;
if (filter.length > 0) {
applyFilter = true;
}
for (i; i < length; i++) {
customer = customers[i];
if (applyFilter && customer.innerHTML.toLowerCase().indexOf(filter) < 0) {
$(customer).addClass('hidden');
} else {
$(customer).removeClass('hidden');
}
}
}
我在网页上有一个包含大约 10 000 个客户的列表,需要能够在此列表中搜索匹配的输入。它有一些延迟,我正在寻找提高性能的方法。这是我使用的 HTML 和 JavaScript 的简化示例:
<input id="filter" type="text" />
<input id="search" type="button" value="Search" />
<div id="customers">
<div class='customer-wrapper'>
<div class='customer-info'>
...
</div>
</div>
...
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#search").on("click", function() {
var filter = $("#filter").val().trim().toLowerCase();
FilterCustomers(filter);
});
});
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-wrapper").show();
return;
}
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).parent().show();
} else {
$(this).parent().hide();
}
});
}
</script>
问题是,当我点击“搜索”按钮时,有很长的延迟,直到我得到包含匹配结果的列表。有没有更好的方法来过滤列表?
问题是你正在迭代记录,如果有 10000 条记录,它可能会很慢,所以我的建议是稍微改变结构,这样你就不必迭代了:
在
customer-wrapper
上定义列表的所有 css 特征 class 并使其成为所有列表元素的 父级 div.当您的 ajax 请求添加一个元素时,创建一个包含名称的变量来替换下划线的空格,我们称之为
underscore_name
.将名称添加到列表中:
var customerHtml = "<div id='"+underscore_name+'>" + name + "</div>";
列表中的每个元素都有一个与名称"almost"相同的唯一 ID,并且列表中的所有元素都在 同一级别 在 customer-wrapper
class.
- 对于搜索,您可以将用户输入的空格替换为下划线并放入变量中,例如
searchable_id
,然后使用 Jquery:
$('#'+searchable_id).siblings().hide()
;
siblings
将隐藏与 searchable_id.
它可能遇到的唯一问题是出现两个或更多重复名称的情况,因为它会尝试创建两个或更多具有相同 ID 的 div。
您可以在 http://jsfiddle.net/mqpsppxm/ 上查看一个简单的实现
感谢您的所有回答和评论,我至少得到了令人满意的性能结果的解决方案。我已经清理了多余的包装器并将列表中的元素 showing/hiding 分组,而不是对每个元素单独进行。下面是过滤现在的样子:
function FilterCustomers(filter) {
if (filter == "") {
$(".customer-info").show();
} else {
$(".customer-info").hide();
$(".customer-info").removeClass("visible");
$(".customer-info").each(function() {
if ($(this).html().toLowerCase().indexOf(filter) >= 0) {
$(this).addClass("visible");
}
});
$(".customer-info.visible").show();
}
}
1) DOM 操作通常很慢,尤其是当您追加新元素时。将所有 html 放入一个变量中并附加它,这会导致一个 DOM 操作并且比对每个元素
快得多function LoadCustomers() {
var count = 10000;
var customerHtml = "";
for (var i = 0; i < count; i++) {
var name = GetRandomName() + " " + GetRandomName();
customerHtml += "<div class='customer-info'>" + name + "</div>";
}
$("#customers").append(customerHtml);
}
2) jQuery.each() 很慢,请改用 for
循环
function FilterCustomers(filter) {
var customers = $('.customer-info').get();
var length = customers.length;
var customer = null;
var i = 0;
var applyFilter = false;
if (filter.length > 0) {
applyFilter = true;
}
for (i; i < length; i++) {
customer = customers[i];
if (applyFilter && customer.innerHTML.toLowerCase().indexOf(filter) < 0) {
$(customer).addClass('hidden');
} else {
$(customer).removeClass('hidden');
}
}
}