html标准中没有onlongpress属性,所有长按功能必须通过javascript手动模拟:监听touchstart启动定时器,配合touchend/touchcancel清除,pc端需防抖动与拖拽误触,并注意回调时dom存在性校验。

为什么不能直接写 onlongpress
HTML 标准里压根没有 onlongpress 这个属性,写在标签上完全无效。浏览器不会识别,也不会触发任何逻辑。所有“长按”都是靠 JavaScript 手动模拟出来的——本质就是:按下时启动计时器,松开前没被清除且超时了,才算长按。
touchstart + setTimeout 是移动端唯一可靠起点
真机环境(iOS Safari / Android Chrome)必须监听 touchstart,而不是 mousedown。后者在启用了 touch-action: manipulation 的页面上大概率不触发,尤其在按钮这类可点击元素上。
-
touchstart中立即调用e.preventDefault(),防止 iOS 高亮或文本选中干扰 - 设一个
setTimeout,阈值建议 700–800ms:短于 500ms 易误触,长于 1s 用户会觉得卡顿 - 必须同时监听
touchend和touchcancel,后者处理手指滑出、页面滚动中断等异常释放场景 - 定时器变量(如
longPressTimer)要声明在闭包或组件实例内,避免多个按钮共用同一变量导致冲突
PC 端兼容不能只靠 mousedown
桌面浏览器没触摸事件,但直接套用 mousedown/mouseup 极易误判:鼠标轻点抖动、拖拽中途松手都会触发长按。必须加防护:
- 监听
mousemove,记录按下时的clientX/clientY,移动超过 10px 就clearTimeout(longPressTimer) -
mouseup必须发生在同一元素上,否则可能是拖拽离开或移出区域 - 给按钮加
style="user-select: none",防止 PC 端长按时意外选中文本 - 不推荐为同一按钮同时绑定
click和长按逻辑——click在移动端有约 300ms 延迟,会和长按判断打架
回调执行前最容易漏掉的三件事
长按回调函数看似简单,但实际运行时容易因环境变化崩掉:
- 元素已被移除或 DOM 被重绘,但定时器还在跑 → 回调里访问
this.$el或element.querySelector报错;需提前校验element.isConnected - 用户快速连点,多次触发
touchstart,却没清理前一个定时器 → 出现重复执行;每次start前先if (timer) clearTimeout(timer) - 菜单弹出后没关前一个,或新菜单定位计算用的是已滚动的
pageX/Y→ 视口滚动后菜单飘走;优先用getBoundingClientRect()+window.scrollX定位
真正麻烦的不是写出来,而是手指刚按下去就切到其他 App、iframe 里 touch 事件丢失、iOS Safari 在后台恢复时 touchcancel 不触发……这些得靠具体容器补丁,没法靠一段通用代码兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











