如何触发一个延迟的onkeyup事件,直到用户暂停键入?

Bru*_*ros 34 javascript ajax jquery

我有一个textarea,人们输入一些文本(自然),我想这样做,以便偶尔发出一个AJAX请求,以获得有关textarea的内容的一些建议(如堆栈溢出的相关问题,但对于textarea,不是文本输入).问题是我无法在每个按键时执行AJAX请求(它没用,而且非常耗费资源),我不确定最有效的方法是什么(每X个字一次?每隔X秒? 或者是其他东西?).

这样做最好的方法是什么?

先感谢您.

Tim*_*own 66

您可以组合一个keypress事件处理程序,setTimeout以便在按键后发送Ajax请求一定时间,如果在计时器完成之前发生另一次按键,则取消并重新启动计时器.假设你有一个id为'myTextArea'的textarea和一个名为的Ajax回调函数doAjaxStuff:

function addTextAreaCallback(textArea, callback, delay) {
    var timer = null;
    textArea.onkeypress = function() {
        if (timer) {
            window.clearTimeout(timer);
        }
        timer = window.setTimeout( function() {
            timer = null;
            callback();
        }, delay );
    };
    textArea = null;
}

addTextAreaCallback( document.getElementById("myTextArea"), doAjaxStuff, 1000 );
Run Code Online (Sandbox Code Playgroud)

  • 如果您希望能够捕获退格键事件,请使用onkeyup. (3认同)
  • 这是普遍接受的"正确"方式.说得好. (2认同)

Tre*_*vor 12

您正在寻找的是什么debouncing.以下是本机JavaScript中的通用算法:

function debounce(fn, duration) {
  var timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(fn, duration)
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何将其与onkeyup事件一起使用的示例:

function debounce(fn, duration) {
  var timer;
  return function(){
    clearTimeout(timer);
    timer = setTimeout(fn, duration);
  }
}

const txt = document.querySelector('#txt')
const out = document.querySelector('#out')
const status = document.querySelector('#status')

const onReady = () => {
  txt.addEventListener('keydown', () => {
    out.classList.remove('idle')
    out.classList.add('typing')
    status.textContent = 'typing...'
  })
  
  txt.addEventListener('keyup', debounce(() => {
    out.classList.remove('typing')
    out.classList.add('idle')
    status.textContent = 'idle...'
  }, 800))
}

document.addEventListener('DOMContentLoaded', onReady)
Run Code Online (Sandbox Code Playgroud)
#wrapper{
  width: 300px;
}

input{
  padding: 8px;
  font-size: 16px;
  width: 100%;
  box-sizing: border-box;
}

#out{
  margin: 10px 0;
  padding: 8px;
  width: 100%;
  box-sizing: border-box;
}

.typing{
  background: #A00;
  color: #FFF;
}

.idle{
  background: #0A0;
  color: #FFF;
}
Run Code Online (Sandbox Code Playgroud)
<div id="wrapper">
  <input id="txt" placeholder="Type here" />
  <div id="out">Status: <span id="status">waiting...</span></div>
</div>
Run Code Online (Sandbox Code Playgroud)


Bri*_*ead 10

另一种方法是使用一个名为bindWithDelay的小型jQuery插件.它使用与接受的答案相同的setTimeout技术,但透明地处理超时,因此您的代码更容易阅读.该源代码可以看出在github.

$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)
Run Code Online (Sandbox Code Playgroud)