如何在用户停止输入后执行一个函数?

52 阅读2分钟

在一定程度的非活动后执行一个函数被称为退避。在许多情况下,跳转是有帮助的。网络开发中最流行的应用之一是在用户停止在文本框中输入文字后执行搜索或过滤一些结果。

一个快速的例子。筛选城市

假设我们的文档中有一个我们想要过滤的城市列表。我们不希望不断地执行过滤功能,而只是在用户 "完成 "输入后才执行。由于我们并不真正知道用户何时完成,我们可以猜测,如果用户停顿一秒钟,我们就可以安全地执行该函数。(这可能会根据你的使用情况而有所不同)。

最终,我们希望我们的效果看起来像这样。

image.png

我们相应的HTML看起来像这样。

<body>
  <input type="text" id="city-filter" />
  <ul id="city-list">
    <li>Boston</li>
    <li>New Brunswick</li>
    <li>New York</li>
    <li>Philadelphia</li>
    <li>Washington</li>
    <li>Wilmington</li>
  </ul>
</body>

这将如何工作

调试背后的想法是,我们有一个全局的JavaScript变量,它将持有对一个setTimeout 的引用。

然后,我们在我们的input ,有一个keyup 事件监听器。当这个事件被触发时,我们会清除全局定时器(如果它正在运行)。这意味着只有在指定的超时前没有被清除的情况下,计时器才会启动--换句话说,只有在超时前没有keyup 事件的情况下,它才会启动。

以下是JavaScript中的情况。

let timer;
const input = document.querySelector('#city-filter');
input.addEventListener(function (e) {
  // Clears any outstanding timer
  clearTimeout(timer);
  // Sets new timer that may or may not get cleared
  timer = setTimeout(() => {
    // Only fires if not cleared
  }, 1000);
});

为我们的用例填空

现在我们所要做的就是为我们的用例填空了。我将通过遍历ul #city-list 元素的所有children ,并相应地更新style.display 属性来做到这一点。

let timer;
const input = document.querySelector('#city-filter');
input.addEventListener(function (e) {
  // Clears any outstanding timer
  clearTimeout(timer);
  // Sets new timer that may or may not get cleared
  timer = setTimeout(() => {
    const items = document.querySelector('#city-list').children;
    for (let item of items) {
      item.style.display = item.textContent.includes(e.target.value)
        ? 'list-item'
        : 'none';
    }
  }, 1000);
});

就这样了!

整个代码

你可以自己运行一个完整的应用程序,其代码如下。

<!DOCTYPE html>
<html>
  <head>
    <title>Debouncing in JavaScript</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <input type="text" id="city-filter" />
    <ul id="city-list">
      <li>Boston</li>
      <li>New Brunswick</li>
      <li>New York</li>
      <li>Philadelphia</li>
      <li>Washington</li>
      <li>Wilmington</li>
    </ul>

    <script>
      let timer;
      const input = document.querySelector('#city-filter');
      input.addEventListener('keyup', function (e) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          const items = document.querySelector('#city-list').children;
          for (let item of items) {
            item.style.display = item.textContent.includes(e.target.value)
              ? 'list-item'
              : 'none';
          }
        }, 1000);
      });
    </script>
  </body>
</html>

你可以在CodeSandbox上看到它的运行情况。