移动端手势滑动时 touchmove 事件为啥不触发?
我在做一个移动端的滑动组件,绑定了 touchstart 和 touchmove 事件,touchstart 能正常触发,但手指滑动时 touchmove 完全没反应,这是为啥?
试过在 Chrome DevTools 的设备模拟器和真机上都测试了,还加了 passive: false,但还是不行。是不是哪里漏了?我的代码大概是这样的:
element.addEventListener('touchstart', handleStart, { passive: false });
element.addEventListener('touchmove', handleMove, { passive: false });
function handleMove(e) {
console.log('move!', e.touches[0].clientX);
}
你代码写得没问题,但大概率漏了一个关键的 CSS 属性:
touch-action。浏览器默认会把触摸事件拿去处理页面滚动、缩放这些手势,导致 touchmove 被浏览器"吃掉"了。虽然你加了
passive: false,但这只是告诉浏览器"我会调用 preventDefault",并不代表浏览器就不会优先处理默认手势行为了。解决方法很简单,给你的滑动元素加上这个 CSS:
或者用 JS 动态设置也行:
加上之后 touchmove 应该就能正常触发了。
还有个坑要注意,如果你只是做水平滑动,不想禁用垂直滚动,可以设成
touch-action: pan-y;,这样垂直方向还能正常滚动,水平方向交给你自己处理。我当时做轮播图组件就是用的这个值,体验会好很多。另外检查一下你的元素是不是真的绑定到了正确的 DOM 上,有没有被其他元素遮挡,有时候 pointer-events 或者 z-index 也会搞事情。可以在 touchstart 里打印一下
e.currentTarget确认下。试试看,应该能解决。