alert() 不会锁定 body 滚动,仅阻塞 JS 执行;禁用滚动需结合 overflow: hidden(注意时机与恢复)及 touchmove 事件拦截(passive: false),自定义弹窗才可控。

点击 alert() 时页面还在滚动?这不是 bug,是预期行为
原生 alert() 确实会阻塞 JavaScript 执行,但**不会自动锁定 的滚动**。所谓“背景不滚动”,其实是浏览器在模态对话框激活时对 scrollbar 的视觉遮蔽或 overflow 的临时干预——而这个干预,alert() 本身并不触发。你看到的“静止”,往往只是因为 JS 被卡住、用户无法操作滚动条,而非 CSS 层面的锁定。
overflow: hidden 加在 上就完事了?别急,先看场景
如果你用的是自定义弹窗(比如 modal),手动加 overflow: hidden 到 是常见做法,但要注意三点:
- 必须在弹窗 显示前 设置,否则可能出现滚动条闪现
- 弹窗关闭后,要恢复原来的
overflow值(不能硬写auto,因为有些页面初始就是hidden或scroll) - 移动端 Safari 对
body { overflow: hidden }支持不稳定,更推荐作用于或用position: fixed配合top: 0补偿
想彻底禁用滚动?touchmove 事件拦截比 CSS 更可靠
仅靠 CSS 在 iOS 上经常失效,尤其当用户用手指快速滑动时。更稳妥的方式是监听并阻止默认行为:
let preventScroll = () => {
window.addEventListener('touchmove', (e) => e.preventDefault(), { passive: false });
};
let allowScroll = () => {
window.removeEventListener('touchmove', (e) => e.preventDefault(), { passive: false });
};
注意:{ passive: false } 必须显式传入,否则现代浏览器会忽略 e.preventDefault();且该方案需与 overflow CSS 配合使用,单靠事件拦截可能影响页面内可滚动区域(如弹窗里的长列表)。
立即学习“前端免费学习笔记(深入)”;
为什么不用 alert() 做业务提示?它绕不开这些限制
原生 alert() 无法定制样式、无法绑定按钮回调、无法阻止背景交互逻辑——更重要的是,它会完全中断 JS 执行栈,导致:
- 计时器(
setTimeout、setInterval)暂停 - Promise 回调、
requestAnimationFrame全部挂起 - Vue/React 组件更新被冻结,状态不同步
- 无法捕获用户是否点了“确定”,更无法做埋点或 A/B 测试
真正需要“禁止背景滚动”的场景,几乎都意味着你在构建一个可控的 UI 层级,这时候 alert() 就不是解决方案,而是问题源头。



















