本文介绍在启用 `scroll-behavior: smooth` 的页面中,如何避免锚点链接触发的平滑滚动误触 scroll 事件,推荐使用 `wheel` 事件替代 `scroll` 事件,并辅以节流控制,实现仅响应真实用户滚动操作。
在现代 Web 开发中,为提升用户体验,常通过 CSS 设置 html { scroll-behavior: smooth; } 实现原生平滑锚点跳转。但该特性会触发 scroll 事件(即使由 点击引发),导致你无法区分「用户手动滚动」与「程序化/导航式滚动」——这在需监听真实滚动行为的场景(如懒加载、滚动进度条、吸顶导航等)中尤为棘手。
直接监听 scroll 事件并尝试在点击时临时移除监听器(如 removeEventListener)并不可靠:
- 平滑滚动是异步且持续数百毫秒的,你无法准确预判其何时开始/结束;
- 多次快速点击或键盘导航(如 Tab + Enter)易造成监听器状态错乱;
- scroll 事件本身在平滑滚动期间高频触发,加剧误判风险。
✅ 更稳健的解决方案:改用 wheel 事件
wheel 事件仅在用户通过鼠标滚轮、触摸板滚动或键盘(空格/方向键)主动触发滚动时触发,而不会被 scroll-behavior: smooth 的锚点跳转、window.scrollTo() 或 element.scrollIntoView() 等 API 触发。因此,它天然区分了「人为滚动」与「声明式导航滚动」。
以下是优化后的完整实现: