为什么 touchmove 事件在移动端会触发多次甚至卡顿?
我在做一个滑动删除功能,监听了 touchstart 和 touchmove,但发现手指稍微一动就触发好多次 touchmove,而且页面还会卡一下。是不是我哪里写错了?
我试过用 e.preventDefault() 但好像没用,代码大概是这样:
element.addEventListener('touchmove', (e) => {
const touch = e.touches[0];
console.log('移动位置:', touch.clientX, touch.clientY);
// 这里做了一些 DOM 操作
});
首先,确保你在 touchmove 事件中没有做耗时操作。DOM 操作比较耗性能,尽量减少或者优化这些操作。你可以尝试只更新必要的部分,或者使用 requestAnimationFrame 来限制更新频率。
其次,使用 e.preventDefault() 是正确的做法,它能防止默认的滚动行为,从而避免浏览器在处理 touchmove 事件时出现不必要的重绘。不过,如果你在 touchstart 或者 touchmove 中阻止了默认行为,可能会导致其他触摸事件无法正常工作,所以要注意这一点。
最后,为了安全起见,确保你的事件处理器不会抛出未捕获的异常,否则可能会导致整个应用崩溃。你可以用 try...catch 块来包裹事件处理逻辑。
这里有一个简单的优化示例,使用 requestAnimationFrame 来限制更新频率:
这段代码通过设置一个阈值来减少 touchmove 的处理次数,并且使用 requestAnimationFrame 来优化 DOM 更新。注意安全,确保你的应用在各种情况下都能稳定运行。
两个解决办法:
一是用节流,把 DOM 操作从每次 touchmove 变成每隔一帧执行一次:
二是别直接改 left/top、width 这些会触发重排的属性,用 transform: translate() 这种 GPU 加速的属性,流畅得多。
还有,绑定事件时别忘了 passive: false,否则 preventDefault 是不生效的,不过看你的场景应该是不想阻止默认滚动,那就用上面第一种办法就行。