协慌网

登录 贡献 社区

如何延迟. keyup()处理函数,直到用户停止键入?

我有一个搜索字段。现在,它会搜索每个键。因此,如果有人键入 “Windows”,它将使用 AJAX 搜索每个键入的内容:“W”,“Wi”,“Win”,“Wind”,“Windo”,“Window”,“Windows”。

我希望有一个延迟,因此它仅在用户停止键入 200 毫秒时才进行搜索。

keyup函数中没有为此选项,并且我已经尝试过setTimeout ,但是它没有用。

我怎样才能做到这一点?

答案

我将这个小功能用于相同的目的,是在用户停止输入指定的时间后或在触发率很高的事件(例如resize执行一个功能:

function delay(callback, ms) {
  var timer = 0;
  return function() {
    var context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function () {
      callback.apply(context, args);
    }, ms || 0);
  };
}


// Example usage:

$('#input').keyup(delay(function (e) {
  console.log('Time elapsed!', this.value);
}, 500));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="input">Try it:
<input id="input" type="text" placeholder="Type something here..."/>
</label>

这个怎么运作:

delay函数将返回一个包装的函数,该函数在内部处理单个计时器,在每次执行中,计时器都将按提供的时间延迟重新启动,如果在此时间过去之前发生了多次执行,则计时器将重置并重新启动。

当计时器最终结束时,将执行回调函数,并传递原始上下文和参数(在此示例中,是 jQuery 的事件对象,而 DOM 元素是this )。

更新 2019-05-16

我已经针对现代环境使用 ES5 和 ES6 功能重新实现了该功能:

function delay(fn, ms) {
  let timer = 0
  return function(...args) {
    clearTimeout(timer)
    timer = setTimeout(fn.bind(this, ...args), ms || 0)
  }
}

该实现包含一组测试

对于更复杂的内容,请看一下 jQuery Typewatch插件。

如果要在类型完成后进行搜索,请使用全局变量来保存从setTimout调用返回的超时,如果尚未发生,请使用clearTimeout keyup外,不会触发超时事件

var globalTimeout = null;  
$('#id').keyup(function(){
  if(globalTimeout != null) clearTimeout(globalTimeout);  
  globalTimeout =setTimeout(SearchFunc,200);  
}   
function SearchFunc(){  
  globalTimeout = null;  
  //ajax code
}

或具有匿名功能:

var globalTimeout = null;  
$('#id').keyup(function() {
  if (globalTimeout != null) {
    clearTimeout(globalTimeout);
  }
  globalTimeout = setTimeout(function() {
    globalTimeout = null;  

    //ajax code

  }, 200);  
}

CMS 答案的另一个小改进。要轻松考虑单独的延迟,可以使用以下方法:

function makeDelay(ms) {
    var timer = 0;
    return function(callback){
        clearTimeout (timer);
        timer = setTimeout(callback, ms);
    };
};

如果您想重复使用相同的延迟,只需执行

var delay = makeDelay(250);
$(selector1).on('keyup', function() {delay(someCallback);});
$(selector2).on('keyup', function() {delay(someCallback);});

如果您想要单独的延迟,可以执行

$(selector1).on('keyup', function() {makeDelay(250)(someCallback);});
$(selector2).on('keyup', function() {makeDelay(250)(someCallback);});