如何仅在Overlay显示时阻止键盘控制网页滚动?
问题原因与解决方案
你的代码之所以出现「关闭Overlay后方向键仍被劫持」的问题,核心原因是:你在launchOverlay和closeOverlay里分别创建了两个完全独立的匿名函数,removeEventListener无法匹配到之前添加的监听函数,导致事件监听根本没被移除。
正确实现步骤
- 把阻止滚动按键的逻辑抽成具名函数,确保添加和移除监听时用同一个函数引用
- 用类名控制Overlay的显示/隐藏(比直接修改style更可靠、易维护)
- 在Overlay打开时绑定事件监听,关闭时移除
修正后的完整代码
共用事件处理函数
// 定义共用的阻止滚动按键函数 function preventScrollKeys(e) { const blockedKeys = [' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']; if (blockedKeys.includes(e.code)) { e.preventDefault(); } }
Overlay控制函数
function launchOverlay() { // 用类名激活Overlay(需配合CSS) overlay.classList.add('active'); // 绑定阻止滚动的监听 window.addEventListener('keydown', preventScrollKeys); } function closeOverlay() { overlay.classList.remove('active'); // 移除监听,此时能匹配到之前添加的函数 window.removeEventListener('keydown', preventScrollKeys); }
Overlay内部按键逻辑
document.addEventListener('keydown', function(event) { // 用类名判断Overlay是否处于激活状态,比读style更可靠 if (overlay.classList.contains('active')) { switch(event.code) { case 'Space': space(); break; case 'ArrowUp': aUp(); break; case 'ArrowDown': aDown(); break; case 'ArrowLeft': aLeft(); break; case 'ArrowRight': aRight(); break; case 'Escape': closeOverlay(); break; } } });
配套CSS
/* 默认隐藏Overlay */ .overlay { display: none; } /* 激活时显示 */ .overlay.active { display: flex; }
额外说明
- 用类名控制DOM状态,能避免直接读取
style.display的误差(比如如果通过其他CSS规则控制显示,直接读style会不准确) - 把阻止滚动的逻辑和Overlay内部按键逻辑分开,代码结构更清晰,也便于后续维护
内容的提问来源于stack exchange,提问作者Eager to Learn
相关产品推荐
相关产品推荐

