Javascript 如何使用setTimeout/.delay()在字符之间等待键入

Javascript 如何使用setTimeout/.delay()在字符之间等待键入,javascript,jquery,listbox,delay,settimeout,Javascript,Jquery,Listbox,Delay,Settimeout,我正在创建一个简单的listbox过滤器,它接受用户输入,并通过javascript/jquery在listbox中返回匹配结果(listbox中大约有5000多个项)。以下是代码片段: var Listbox1 = $('#Listbox1'); var commands = document.getElementById('DatabaseCommandsHidden'); //using js for speed $('#CommandsFilter').bind('keyup', fu

我正在创建一个简单的listbox过滤器,它接受用户输入,并通过javascript/jquery在listbox中返回匹配结果(listbox中大约有5000多个项)。以下是代码片段:

var Listbox1 = $('#Listbox1');
var commands = document.getElementById('DatabaseCommandsHidden'); //using js for speed

$('#CommandsFilter').bind('keyup', function() {

Listbox1.children().remove();


for (var i = 0; i < commands.options.length; i++) {
    if (commands.options[i].text.toLowerCase().match($(this).val().toLowerCase())) {
        Listbox1.append($('<option></option>').val(i).html(commands.options[i].text));
    }
}
});
var Listbox1=$('#Listbox1');
var commands=document.getElementById('DatabaseCommandsHidden')//使用js提高速度
$('#CommandsFilter').bind('keyup',function(){
Listbox1.children().remove();
对于(var i=0;i
这工作得很好,但是当输入第1/2个字符时,速度会有所减慢,因为项目太多了

我认为我可以使用的解决方案是在文本框中添加延迟,以防止在用户停止键入之前调用“keyup”事件。问题是,我不知道该怎么做,或者这是否是个好主意


非常感谢您的任何建议/帮助。

您可以这样延迟:

$('#CommandsFilter').keyup(function() {
  clearTimeout($.data(this, 'timer'));
  var wait = setTimeout(search, 500);
  $(this).data('timer', wait);
});

function search() {
  var temp = $("<select />");
  for (var i = 0; i < commands.options.length; i++) {
    if (commands.options[i].text.toLowerCase().match($(this).val().toLowerCase())) {
      $('<option></option>', { val: i, html: commands.options[i].text }).appendTo(temp);
    }
  }
  Listbox1.empty().append(temp.children());
}
$('#CommandsFilter').keyup(函数(){
clearTimeout($.data(此为“计时器”);
var wait=setTimeout(搜索,500);
$(this).data('timer',wait);
});
函数搜索(){
变量温度=$(“”);
对于(var i=0;i

这会在您输入的元素上存储一个超时,如果两次击键之间经过500毫秒(根据需要调整),则会执行搜索。此外,这还会将文档片段中的元素附加到DOM中(仍然保留编码等)。根据项目的数量,这可能也是一个不错的性能提升。

如果命令下拉列表没有改变,我建议如下(注意,为了更好的性能和兼容性,我已经删除了jQuery)。有几项改进:

  • 定时器,用于在上次按键后半秒后延迟更新过滤列表
  • 命令文本列表已预缓存
  • 不必要地使用
    match
    替换为
    indexOf
  • 使用自20世纪90年代以来在所有可编写脚本的浏览器中工作的快速本机DOM操作
快速测试表明,对于包含5000个选项(包含短字符串)的下拉列表,它比大多数浏览器中的jQuery等价项快10到30倍

代码:

var commands=document.getElementById(“DatabaseCommandsHidden”);
var filteredDropDown=document.getElementById(“Listbox1”);
var filterInput=document.getElementById(“CommandsFilter”);
无功定时器;
//创建命令下拉列表中小写文本的缓存列表
var commandText=[],commandText;
对于(变量i=0,len=commands.options.length;i-1){
opts[opts.length]=新选项(commandText.original);
}
}
}
filterInput.onkeyup=函数(){
中频(定时器){
清除超时(计时器);
}
定时器=window.setTimeout(populateFilteredDropDown,500);
};

我认为没有比串接一个字符串并附加该块更快的方法了。@jAndy-这取决于有多少个元素,当前您的选项也没有设置值,所以这是作弊;)性能问题每隔一段时间就会出现一次,实际上有一天我有时间在这里提供一些示例:将
$(this).val().toLowerCase()
移动到循环外部定义的变量中,会带来另一个速度提升。@Nick:修复了作弊:p--DOM缓存的东西,如果您不每次添加完全相同的html部分,它仍然有效吗?@jAndy-它根据字符串缓存文档片段,因此
$(htmlHere)
中的部分需要保持一致,因为这是关键。您的解决方案会产生小写结果,而OP没有这样做,他正在进行不区分大小写的搜索,但不是将结果选项的大小写降低,还需要将值降低大小写,因为这也不会进行不区分大小写的搜索。
var commands = document.getElementById("DatabaseCommandsHidden");
var filteredDropDown = document.getElementById("Listbox1");
var filterInput = document.getElementById("CommandsFilter");
var timer;

// Create a cached list of the lower case text of the commands drop-down
var commandTexts = [], commandText;
for (var i = 0, len = commands.options.length; i < len; ++i) {
    commandText = commands.options[i].text;
    commandTexts.push({original: commandText, lower: commandText.toLowerCase()});
}

function populateFilteredDropDown() {
    timer = null;
    var val = filterInput.value.toLowerCase(), commandText;
    var opts = filteredDropDown.options;
    filteredDropDown.length = 0;
    for (var i = 0, len = commandTexts.length; i < len; ++i) {
        commandText = commandTexts[i];
        if (commandText.lower.indexOf(val) > -1) {
            opts[opts.length] = new Option(commandText.original);
        }
    }
}

filterInput.onkeyup = function() {
    if (timer) {
        window.clearTimeout(timer);
    }
    timer = window.setTimeout(populateFilteredDropDown, 500);
};