touchmove 事件在 React 中为什么不触发?

Good“统元 阅读 31

我在写一个移动端的滑动组件,给 div 加了 onTouchMove 事件,但手指滑动时完全没反应,onTouchStart 和 onTouchEnd 都能正常触发,就 touchmove 不行,这是为啥?

我试过加 passive: false,也试过用原生 addEventListener,但问题依旧。是不是 React 的合成事件有什么坑?

function SwipeBox() {
  const handleTouchMove = (e) => {
    console.log('moving', e.touches[0].clientX);
  };

  return (
    <div
      onTouchStart={() => console.log('start')}
      onTouchMove={handleTouchMove}
      onTouchEnd={() => console.log('end')}
      style={{ width: '100%', height: '200px', background: '#eee' }}
    />
  );
}
我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
Mr-依甜
Mr-依甜 Lv1
啊这问题我踩过坑!根本原因是移动端浏览器默认会阻止 touchmove 事件的默认行为来优化滚动性能。React 的合成事件其实没啥问题,但我们需要阻止默认行为。

给你两个解决方案,选一个就行:

1. 简单粗暴版,直接在 touchmove 事件里加 e.preventDefault():
const handleTouchMove = (e) => {
e.preventDefault();
console.log('moving', e.touches[0].clientX);
};


2. 优雅点的方式,给 div 加个 CSS 属性 touch-action: none,这样浏览器就知道你不需要默认的滚动行为:
<div
// 其他属性...
style={{
width: '100%',
height: '200px',
background: '#eee',
touchAction: 'none' // 关键在这行
}}
/>


个人推荐第二种方案,这样逻辑和样式分离更清晰,而且性能更好。第一种方案可能会在某些浏览器触发警告说 preventDefault 在 passive 事件上无效。

记得如果之后需要恢复默认滚动行为,可以把 touch-action 改成 auto 或者 pan-x/pan-y 这种具体值。
点赞
2026-03-09 03:08
夏侯慧慧
十有八九是 CSS 的 touch-action 没设置,浏览器把触摸事件"吞"掉了去做页面滚动了。给那个 div 加上 touch-action: none 就行,改成这样:

function SwipeBox() {
const handleTouchMove = (e) => {
console.log('moving', e.touches[0].clientX);
};

return (
onTouchStart={() => console.log('start')}
onTouchMove={handleTouchMove}
onTouchEnd={() => console.log('end')}
style={{
width: '100%',
height: '200px',
background: '#eee',
touchAction: 'none'
}}
/>
);
}


移动端浏览器默认会拦截 touchmove 用来处理页面滚动,你不告诉它"别动,让我自己处理",它就直接给你滚走了,事件根本不会触发。这个坑踩过好几次了。
点赞 3
2026-03-02 00:12