刚果有1000万个问题!
我有一个包含行的表> 200。 我搜索表行中的特定文本,如果文本存在(作为行中的子字符串),我遍历行并使它们可见。如果文本不存在,我会使它们不可见。我在text-field上使用输入监听器来检测键入的文本:
$(document).ready(function () { //bind when DOM ready
$('[name="token_search"]').on("input", function (evt) { //listener on textfield
if ($(this).val() == "") { //if no text-show all rows
$(".tokens-table tr").show();
return;
} else { //filter rows based on typed text
$(".tokens-table tr").each(function (index) {
if (index > 1) //do not hide first two rows
if ($(this).children()[0].innerHTML.indexOf($('[name="token_search"]').val()) != -1) {
$(this).show();
} else {
$(this).hide();
}
});
}
});
});
当用户键入文本时,该方法将对>上的每个输入事件进行子字符串搜索。 200项。当用户键入太快或在低端设备上时,这会导致UI被挂起。如何修改上面的代码,仅针对搜索字段上的最后一个输入事件执行,而不是对队列中的所有输入事件执行?我的意思是一旦用户键入一个新字符,我就希望清除队列中的所有先前事件。
答案 0 :(得分:3)
基本上你需要使用一个计时器来等待用户停止输入一段时间,然后调用你的函数。并且你应该在你的代码中多次使用它们时缓存元素和值,正如charlietfl指出的那样。以下应该可以解决问题。:
老实说,如果您的目的是创建一个过滤表格的搜索框,您可能需要查看DataTables,它可以很好地完成过滤等工作。
$(document).ready(function() { //bind when DOM ready
$('[name="token_search"]').on("keyup", function(evt) { //listener on textfield
var $this = $(this);
var value = $this.val(); // incorporated charlietfl's improvements
// cache the value of the search input and this
delay(function() {
$(".tokens-table tr:gt(1)").each(function(index, element) {
var $element = $(element);
$this.val() == "" || $element.children()[0].innerHTML.indexOf(value) != -1 ? $element.show() : $element.hide();
});
}, 700); // waits till the user has stopped typing for 7/10 of a second, adjust as needed
// 1000 = 1 second
});
});
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="token_search" id=""><br><br>
<table class="tokens-table">
<tr>
<td>unfilterable row</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>unfilterable row</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>one</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>two</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>one</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>four</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>one</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>three</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>two</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>one</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>three</td>
<td>some data</td>
<td>some data</td>
</tr>
<tr>
<td>one</td>
<td>some data</td>
<td>some data</td>
</tr>
</table>
&#13;
答案 1 :(得分:2)
代码中一个非常昂贵的部分是在每次迭代中搜索dom,以获取事件处理程序本身内已有的input
的值。
执行一些值和jQuery对象的缓存。
这段代码非常昂贵:
.... indexOf($('[name="token_search"]').val())
相反:
$('[name="token_search"]').on("keyup", function (evt) {
var value = this.value;
if (value)...
....
.... indexOf(value)
这将删除100个DOM搜索相同的值
同样,如果您对同一$(this)
多次使用this
,请将其缓存为变量
$(".tokens-table tr").each(function (index) {
var $this = $(this);
if ($this.children()[0].innerHTML.indexOf(value) != -1) {
$this.show();
}
});
如果这些改进无效,那么您还可以实施其他解决方案,例如throttling
或debouncing
使用计时器搜索之间的时间