我有一个搜索框,隐藏列表中不包含输入文本的所有行。
这项工作很有效,直到该列表变为10,000行。一次击键很好,但如果用户输入多个字母单词,则会为每个按键重复该功能。
如果按下新键,我想要放弃之前执行的任何功能。
该功能非常简单,如下:
$("#search").keyup(function(e) {
goSearch();
});
function goSearch()
{
var searchString = $("#search").val().toLowerCase();
$(".lplist").each(function(index, element) {
var row = "#row-" + element.id.substr(5);
if ($(element).text().toLowerCase().indexOf(searchString,0) != -1)
$(row).show();
else
$(row).hide();
});
}
由于
答案 0 :(得分:0)
引入一个由keypress事件处理程序增加的计数器var keypressCount
。在goSearch()
的开头将其值写入缓冲区。然后,在$(".lplist").each()
的每次运行中,您询问当前keypressCount
是否与缓冲的for()
相同;如果没有,你就回来了。我建议您使用break;
,因为$.each()
比{{1}}更容易。
更新: 您必须确保有时间触发/接收新的按键事件,因此将$ .each()的匿名函数包装在超时内。
参考:http://www.garrickcheung.com/javascript/what-i-learned-about-multi-threading-in-javascript/
答案 1 :(得分:0)
你不能直接。 Javascript不是多线程的,因此您的函数将运行并阻止任何按键操作直到完成。
从用户体验的角度来看,这是可以容忍的方式是不会立即触发关键事件的功能,而是等待一小段时间然后触发事件。
当用户正在键入时,将不断设置和重置超时功能,因此不会调用gosearch函数,因此用户不会中断其输入。
当用户暂停键入时,超时将倒计时到零并调用搜索功能,该功能将运行并阻止键入直到完成。但这没关系(只要它在一秒左右内完成),因为用户可能当前没有尝试输入。
您也可以通过将gosearch函数分解为块来执行您实际要求的操作,其中每次调用函数:*读取到目前为止处理的行数的计数器,然后处理另外500行并递增计数器。 *使用setTimeout调用另一个gosearch,其值为零。这会将事件发送到其他“线程”,并允许快速更改搜索项。
var goSearchTimeout = null;
var linesSearched = 0;
function keySearch(e){
if(goSearchTimeout != null){
clearTimeout(goSearchTimeout);
linesSearched = 0;
}
goSearchTimeout = setTimeout(goSearch, 500);
}
$("#search").keyup(keySearch);
function highLight(index, element) {
if(index >= linesSearched){
var row = "#row-" + element.id.substr(5);
if ($(element).text().toLowerCase().indexOf(searchString,0) != -1){
$(row).show();
else{
$(row).hide();
}
if(index > linesSearched + 500){
linesSearched = index;
goSearchTimeout = setTimeout(goSearch);
return;
}
}
function goSearch(){
goSearchTimeout = null;
var searchString = $("#search").val().toLowerCase();
$(".lplist").each(highLight);
}
如果您打算使用这样的超时回调,我强烈建议将代码包装到jQuery小部件中,这样您就可以使用对象上的变量来存储变量goSearchTimeout等,而不是让它们浮动为全局变量。
答案 2 :(得分:0)
您可以使用全局变量来保存搜索字符串,并在搜索字符串更改时停止执行。
重要:您必须在每次迭代中设置超时,以便暂停函数执行并更新全局变量,因为JavaScript是单线程的。
您的代码如下所示:
var searchString;
$("#search").keyup(function(e) {
// Update search string
searchString = $("#search").val().toLowerCase();
// Get items to be searched
var items = $(".lplist");
// Start searching!
goSearch(items, searchString, 0);
});
function goSearch(items, filter, iterator)
{
// Exit if search changed
if (searchString != filter) {
return;
}
// Exit if there are no items left
if (iterator >= items.length) {
return;
}
// Main logic goes here
var element = items[iterator];
var row = "#row-" + element.id.substr(5);
if ($(element).text().toLowerCase().indexOf(filter, 0) != -1)
$(row).show();
else
$(row).hide();
// Schedule next iteration in 5 ms (tune time for better performance)
setTimeout(function() {
goSearch(items, filter, iterator + 1);
}, 5);
}