You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展:弹窗开启时禁用其他keydown事件,关闭后恢复

实现Chrome扩展对话框的键盘事件隔离与恢复

核心思路

通过在对话框开启时添加捕获阶段的全局keydown拦截器,优先拦截除Esc键外的所有键盘事件;关闭对话框时移除该拦截器,恢复正常的键盘事件流。同时单独监听Esc键用于关闭对话框。

代码实现(Content Script 场景)

// 全局状态与拦截器变量
let isDialogActive = false;
let keyInterceptor = null;

// 打开自定义对话框
function showCustomDialog() {
  isDialogActive = true;

  // 创建非阻塞自定义弹窗
  const dialog = document.createElement('div');
  dialog.style.cssText = `
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    padding: 2rem;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.2);
    z-index: 99999;
  `;
  dialog.textContent = "按下 Esc 键关闭对话框";
  document.body.appendChild(dialog);

  // 注册捕获阶段的键盘拦截器(优先触发)
  keyInterceptor = (e) => {
    // 仅放行 Esc 键
    if (e.key !== 'Escape') {
      e.stopImmediatePropagation(); // 阻止后续同元素的监听器执行
      e.preventDefault(); // 阻止浏览器默认行为(如输入、滚动)
    }
  };
  document.addEventListener('keydown', keyInterceptor, true);

  // 监听 Esc 键关闭对话框
  const handleEscClose = (e) => {
    if (e.key === 'Escape') {
      hideCustomDialog(dialog, handleEscClose);
    }
  };
  document.addEventListener('keydown', handleEscClose);
}

// 关闭自定义对话框并恢复事件
function hideCustomDialog(dialog, escHandler) {
  isDialogActive = false;

  // 移除弹窗元素
  document.body.removeChild(dialog);

  // 移除拦截器与Esc监听器
  document.removeEventListener('keydown', keyInterceptor, true);
  document.removeEventListener('keydown', escHandler);
}

// 示例:绑定某个按键触发对话框(比如Ctrl+Shift+K)
document.addEventListener('keydown', (e) => {
  if (e.ctrlKey && e.shiftKey && e.key === 'K') {
    e.preventDefault();
    if (!isDialogActive) showCustomDialog();
  }
});

关键细节说明

  1. 捕获阶段监听:第三个参数设为true,让拦截器在事件冒泡前优先触发,确保能拦截页面上所有后续注册的keydown监听器。
  2. 事件拦截逻辑:使用stopImmediatePropagation阻止同一事件目标上的其他监听器执行,preventDefault阻止浏览器默认行为(如文本输入、页面滚动)。
  3. 阻塞式弹窗适配:如果使用alert/confirm这类阻塞式弹窗,需将拦截器注册放在弹窗调用前,移除逻辑放在弹窗关闭后:
function showBlockDialog() {
  isDialogActive = true;

  // 先注册拦截器
  keyInterceptor = (e) => {
    if (e.key !== 'Escape') {
      e.stopImmediatePropagation();
      e.preventDefault();
    }
  };
  document.addEventListener('keydown', keyInterceptor, true);

  // 阻塞式弹窗,用户关闭后执行后续代码
  alert("按下 Esc 关闭弹窗");

  // 恢复事件
  isDialogActive = false;
  document.removeEventListener('keydown', keyInterceptor, true);
}

注意事项

  • 若需拦截iframe内的键盘事件,需向iframe注入相同的拦截逻辑,或确保iframe未阻止事件冒泡到顶层document。
  • 确保拦截器仅在对话框开启时存在,避免影响页面正常交互。

内容的提问来源于stack exchange,提问作者tnemele12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 00:37:34