Javascript 如果按下另一个键,则放弃挂起/运行按键功能
我有一个搜索框,隐藏列表中不包含输入文本的所有行 这个方法非常有效,直到列表变成10000行。一次按键就可以了,但是如果用户键入几个字母的单词,该函数将针对每个按键进行迭代 我想做的是,如果按下一个新键,就放弃以前执行的任何函数 功能非常简单,如下所示:Javascript 如果按下另一个键,则放弃挂起/运行按键功能,javascript,jquery,input,Javascript,Jquery,Input,我有一个搜索框,隐藏列表中不包含输入文本的所有行 这个方法非常有效,直到列表变成10000行。一次按键就可以了,但是如果用户键入几个字母的单词,该函数将针对每个按键进行迭代 我想做的是,如果按下一个新键,就放弃以前执行的任何函数 功能非常简单,如下所示: $("#search").keyup(function(e) { goSearch(); }); function goSearch() { var searchString = $("#search").val
$("#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();
});
}
谢谢引入一个计数器
var keypressCount
,该计数器由按键事件处理程序增加。在goSearch()
的开头,将其值写入缓冲区。然后在每次运行$(“.lplist”)。each()
您会询问当前的按键计数是否与缓冲的按键计数相同;如果没有,你就回来。我建议您使用for()
,因为更容易中断代码>大于$。每个()
更新:
您必须确保有时间触发/接收新的按键事件,因此将$.each()的匿名函数包装在一个超时内
参考资料:您不能直接使用。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等,而不是让它们作为全局变量浮动。您可以使用全局变量来保存搜索字符串,并在搜索字符串更改时停止执行
重要信息:您必须在每次迭代中设置超时,以便暂停函数执行并更新全局变量,因为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);
}
聪明的想法,但它不会工作,因为JavaScript是单线程的。调用goSearch()
时,在退出之前不会执行任何其他操作。因此,keypressCount
变量在goSearch()
完成其执行之前不会更新,即使keypress
事件发生在goSearch()
执行期间。如果keypressCount
是一个全局变量,它会更智能。如有必要,请仔细阅读范围。:)您可以从任何函数内部操作全局变量(在函数外部声明),即使在函数返回后,它也会保留其值。当然可以,但由于JavaScript是单线程的,所以在函数完成执行之前不会更新变量。这就是你的解决方案不起作用的原因。很好,我看到你注意到了这一点,并相应地更新了你的答案,:-)javascript是多线程的,这就是为什么你得到了一个事件系统不,不是,这就是为什么你不应该编写长时间运行的函数!我发现:顺便说一句,即使在多线程的环境中,所有GUI事件都倾向于通过一个上下文,实际上都是单线程的。这至少适用于Windows和Java Swing应用程序,在这些应用程序中,写得不好的应用程序可能会通过不快速返回GUI事件通知调用来阻止GUI响应。不要吝啬,请投票支持一些答案,至少是Danack的:-)