应使用 touchstart/touchmove 而非 scroll:scroll 无法捕获滑动起始、方向和速度,且在 iOS Safari 中常被节流;手势识别必须基于 touchstart→touchmove→touchend 生命周期,配合位移阈值、preventDefault 条件调用及 touchcancel 兜底。

滑动事件监听用 touchstart/touchmove 还是 scroll?
直接监听 scroll 事件无法捕获用户手指滑动的起始、方向和速度,它只在滚动实际发生后触发,且在 iOS Safari 中常被节流或延迟。真正做手势识别(比如判断是“上滑翻页”还是“左滑返回”),必须从 touchstart → touchmove → touchend 这套原生触摸生命周期入手。
实操建议:
- 在
touchstart记录初始坐标:startX/startY,并保存timestamp - 在
touchmove中实时计算位移差和耗时,避免直接用event.touches[0].clientX做绝对值比较(要考虑缩放、iframe 偏移) - 务必调用
event.preventDefault()—— 但仅在明确要接管滑动行为时调用,否则会禁用页面默认滚动 - 不要在
touchmove里频繁触发重绘或复杂计算,iOS 上容易卡顿;可加requestAnimationFrame节流
touchmove 阻止默认行为后页面不滚动了,怎么恢复?
这是最常踩的坑:一加 event.preventDefault(),整个页面就“冻住”了。根本原因不是代码写错了,而是你没区分“手势意图”。浏览器需要知道“这段滑动我要自己处理”,还是“这只是用户想滚页面”。
解决方案是引入最小位移阈值 + 方向锁定:
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 在
touchmove中持续计算deltaX和deltaY,仅当Math.abs(deltaY) > Math.abs(deltaX) + 10(竖直主导)且Math.abs(deltaY) > 15时才调用preventDefault() - 用
event.cancelable和event.defaultPrevented检查是否还能阻止(某些 WebView 下可能已失效) - 如果只是做“下拉刷新”,推荐复用
overscroll-behavior: contain配合scrollend事件,比纯 touch 手动实现更稳
iOS Safari 滑动卡顿、touchend 延迟触发怎么办?
iOS Safari 对 touch 事件有约 300ms 的延迟(尤其在非 width=device-width viewport 下),且 touchend 可能因快速滑动被吞掉。这不是 bug,是系统为双击缩放留的判断窗口。
绕过方式很实际:
- 在
<head>加<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">——user-scalable=no是关键,它让 Safari 放弃双击检测逻辑 - 用
touchcancel作为touchend的兜底:iOS 快速滑动时更倾向触发touchcancel,别忽略它 - 避免在
touchstart中做 DOM 查询或样式计算,iOS WebKit 的 JS 主线程响应慢,会拖累后续事件派发
用 PointerEvent 替代 TouchEvent 真的更可靠吗?
在支持的环境里(Chrome 55+、Edge 12+、Safari 13.1+),PointerEvent 确实统一了鼠标/触控/笔输入,但它对滑动手势识别没有本质提升——pointermove 依然需要你自己算位移,pointercancel 依然存在,而且 Safari 对 getCoalescedEvents() 支持不全,导致快速滑动丢点。
结论很直接:新项目可试,老项目别切。尤其要注意:
-
pointerdown的pressure和tangentialPressure在手机上基本无意义,别依赖 - 安卓 Chrome 下
pointermove的触发频率可能低于touchmove,反而影响滑动灵敏度 - 检测兼容性必须用
'onpointerdown' in window,不能只靠 UA 判断
手势识别真正的难点不在事件绑定,而在于如何把原始坐标流转化成稳定、抗噪、低延迟的语义动作。哪怕只加 5px 的容错阈值或 16ms 的防抖,都可能让“左滑删除”从偶发失败变成每次准确触发。


















