jQuery中延迟按键操作的方法

31

我该如何在jQuery中延迟按键事件之间的操作。例如:

我有类似如下代码:

 if($(this).val().length > 1){
   $.post("stuff.php", {nStr: "" + $(this).val() + ""}, function(data){
    if(data.length > 0) {
      $('#suggestions').show();
      $('#autoSuggestionsList').html(data);
    }else{
      $('#suggestions').hide();
    }
 });
}

我想要在用户连续输入时防止提交数据。那么,如何设置0.5秒的延迟?


我假设这是一个传递给keypress()函数的函数内部的代码? - Jeremy
5个回答

66
你可以使用jQuery的data方法来实现这个,像这样:
$('#mySearch').keyup(function() {
  clearTimeout($.data(this, 'timer'));
  var wait = setTimeout(search, 500);
  $(this).data('timer', wait);
});

function search() {
  $.post("stuff.php", {nStr: "" + $('#mySearch').val() + ""}, function(data){
    if(data.length > 0) {
      $('#suggestions').show();
      $('#autoSuggestionsList').html(data);
    }else{
      $('#suggestions').hide();
    }
  });
}

这里的主要优点是没有全局变量散落在各个地方,如果您想要,在setTimeout中可以将其包装成一个匿名函数,只是为了尽可能使示例更加简洁。


11

你只需要在函数外加一个超时计时器,当用户按下键时重置它:

var ref;
var myfunc = function(){
   ref = null;
   //your code goes here
};
var wrapper = function(){
    window.clearTimeout(ref);
    ref = window.setTimeout(myfunc, 500);
}

然后只需在您的键事件中调用 "wrapper"。


3

难道不是所有东西都依赖于jQuery吗?不得不承认,“Debounce”这个名字引起了愤世嫉俗的笑声!无论如何,这是一个好发现。 - C. Tewalt
lodash 还有 throttledebounce 方法。 - Jamie Humphries

2
尼克的答案很完美,但如果立即处理第一个事件是至关重要的,那么我认为我们可以这样做:
$(selector).keyup(function(e){ //or another event

    if($(this).val().length > 1){
        if !($.data(this, 'bouncing-locked')) {

            $.data(this, 'bouncing-locked', true)

            $.post("stuff.php", {nStr: "" + $(this).val() + ""}, function(data){
                if(data.length > 0) {
                    $('#suggestions').show();
                    $('#autoSuggestionsList').html(data);
                }else{
                    $('#suggestions').hide();
                }
           });

            self = this
            setTimeout(function() {
                $.data(self, 'bouncing-locked', false);

                //in case the last event matters, be sure not to miss it
                $(this).trigger("keyup"); // call again the source event
            }, 500)
        }
    }
});

1
我会将它包装在一个函数中,像这样:
  var needsDelay = false;

  function getSuggestions(var search)
  {
    if(!needsDelay)
    {
        needsDelay = true;
        setTimeout("needsDelay = false", 500);

        if($(this).val().length > 1){
            $.post("stuff.php", {nStr: "" + search + ""}, function(data){
                if(data.length > 0) {
                    $('#suggestions').show();
                    $('#autoSuggestionsList').html(data);
                }else{
                    $('#suggestions').hide();
                }
            });
        }
    }


  }

这样无论您 ping 多少次,都不会超过每 500 毫秒搜索一次。


5
永远不要传递字符串给setTimeout!eval是邪恶的(在大多数情况下):)使用匿名函数,如:setTimeout(function() { needsDelay = false; }, 500); - Nick Craver
我知道eval很危险,但我还是懒得在我的代码中加入eval语句。我需要把它加入到我的“纳粹清单”中。不再使用eval。 - thaBadDawg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接