JavaScript 处理 Enter 键事件的技巧

在前端 JavaScript 中处理 keydown 事件时,如果不正确处理 Enter 键(回车键),可能会导致“卡住”或触发无限查询的问题。这通常是因为事件监听器没有适当限制重复触发(例如浏览器的“keydown”事件重复触发机制)或没有清除之前的操作。


问题分析

  1. keydown 事件的重复触发
    • 当用户长按 Enter 键时,浏览器会持续触发 keydown 事件(取决于键盘的重复率),导致查询函数被反复调用。
  2. 未阻止默认行为
    • 如果 Enter 键是在表单中触发的,可能会导致表单提交,从而引发额外的请求。
  3. 没有防抖或节流
    • 没有限制查询的频率,可能导致短时间内发送大量请求。

解决方案

1. 使用 event.preventDefault() 阻止默认行为

如果 Enter 键是在表单中触发的,可以阻止其默认提交行为。

document.addEventListener('keydown', (event) => {
  if (event.key === 'Enter') {
    event.preventDefault(); // 阻止默认行为(如表单提交)
    // 执行你的查询逻辑
    console.log('Enter 键被按下,但不会重复提交');
  }
});

2. 检查 event.repeat 属性

keydown 事件有一个 repeat 属性,当长按键时它会变为 true。可以通过这个属性避免重复触发。

document.addEventListener('keydown', (event) => {
  if (event.key === 'Enter' && !event.repeat) {
    // 只在第一次按下时触发
    console.log('Enter 键按下,执行查询');
    // 在这里调用你的查询函数
  }
});

3. 添加防抖(Debounce)机制

防抖可以确保在短时间内只执行一次查询,即使 Enter 键被快速重复按下。

function debounce(func, delay) {
  let timeoutId;
  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

const handleQuery = debounce(() => {
  console.log('执行查询');
  // 在这里调用你的查询函数
}, 300); // 300ms 延迟

document.addEventListener('keydown', (event) => {
  if (event.key === 'Enter') {
    event.preventDefault();
    handleQuery();
  }
});

4. 添加节流(Throttle)机制

节流可以限制查询的频率,例如每秒最多触发一次。

function throttle(func, limit) {
  let inThrottle;
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

const handleQuery = throttle(() => {
  console.log('执行查询');
  // 在这里调用你的查询函数
}, 1000); // 1秒内最多触发一次

document.addEventListener('keydown', (event) => {
  if (event.key === 'Enter') {
    event.preventDefault();
    handleQuery();
  }
});

5. 结合实际场景:表单输入框

如果你的查询是基于输入框内容的,可以在 Enter 键按下时检查输入值并避免重复查询。

const input = document.querySelector('#searchInput');
let lastQuery = '';

input.addEventListener('keydown', (event) => {
  if (event.key === 'Enter' && !event.repeat) {
    event.preventDefault();
    const query = input.value.trim();
    if (query && query !== lastQuery) { // 避免重复查询相同内容
      lastQuery = query;
      console.log('查询:', query);
      // 在这里调用你的查询函数
    }
  }
});

综合示例

以下是一个结合防抖和重复检查的完整示例:

<input type="text" id="searchInput" placeholder="输入后按 Enter 查询" />
const input = document.querySelector('#searchInput');

function debounce(func, delay) {
  let timeoutId;
  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

const performQuery = debounce((query) => {
  console.log('查询中:', query);
  // 模拟异步请求
  // fetch(`/api/search?q=${query}`).then(response => response.json());
}, 500);

input.addEventListener('keydown', (event) => {
  if (event.key === 'Enter' && !event.repeat) {
    event.preventDefault();
    const query = input.value.trim();
    if (query) {
      performQuery(query);
    }
  }
});

总结

  • 如果只是简单避免重复触发:使用 event.repeat 检查。
  • 如果需要限制查询频率:使用防抖(debounce)或节流(throttle)。
  • 如果在表单中使用:记得调用 event.preventDefault()
  • 如果有输入框:可以添加输入值检查,避免重复查询相同内容。

posted on 2025-03-10 14:41  爱上键盘的蜗牛  阅读(165)  评论(0)    收藏  举报

导航