同一个按钮绑了 touchstart 和 click,手机上点一下提交两次,安卓连着触发两次,iOS 只触发一次,排查时很容易被机型带偏。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
btn.addEventListener('touchend', (e) => {
e.preventDefault();
submit();
}, { passive: false });
touchstart 结束后浏览器仍会补发一个 click,两套监听同时跑,业务逻辑就执行两次,只在手机上暴露,快速点击时更明显。桌面端根本看不出来。这一点先确认清楚,后面就不用反复试。
「touch 与 click 双触发」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。
动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
具体做法是,只保留 click,让浏览器自己去兼容触摸和鼠标,多数场景这样就够了;必须用 touchstart 时,在回调里 preventDefault 挡掉 click,不挡的话逻辑一定跑两遍;加一个时间戳标记,同一位置三百毫秒内不重复处理。
改完照着核一遍,手机上点一次只提交一次,控制台也只打一条请求记录,重复数据不再出现。
