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(); } });
关键细节说明
- 捕获阶段监听:第三个参数设为
true,让拦截器在事件冒泡前优先触发,确保能拦截页面上所有后续注册的keydown监听器。 - 事件拦截逻辑:使用
stopImmediatePropagation阻止同一事件目标上的其他监听器执行,preventDefault阻止浏览器默认行为(如文本输入、页面滚动)。 - 阻塞式弹窗适配:如果使用
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
相关产品推荐
相关产品推荐

