You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

touchmove与mousemove行为差异:移动端目标元素不变问题咨询

移动端touchmove事件target不更新的问题:原因与解决方案

这个问题我之前也碰到过,本质是鼠标事件和触摸事件的目标绑定逻辑完全不同,咱们一步步拆解清楚:

一、为什么会出现这个差异?

  • 鼠标事件(如mousemove):每次鼠标移动时,浏览器都会实时检测光标当前所在的DOM元素,所以event.target会动态更新为光标下方的元素——这就是你在div1按下鼠标滑到div2时,mousemove的target会变成div2的原因。
  • 触摸事件(如touchmove):触摸的整个事件序列(touchstarttouchmovetouchend)是绑定在初始触摸的元素上的。也就是说,你在div1触发touchstart后,不管手指滑到哪个元素,后续touchmoveevent.target都会一直是div1。这是浏览器为了保证触摸交互连贯性(比如拖拽元素)而设计的默认行为。

二、解决办法:手动获取触摸位置的元素

既然浏览器不会自动更新touchmove的target,我们可以在touchmove事件里,通过document.elementFromPoint()方法,根据当前触摸的坐标获取真正位于手指下方的元素,代替原来的event.target

修改后的完整代码

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
div {
display: inline-block;
width: 150px;
height: 150px;
color: red;
border: 1px solid black;
}
</style>
</head>
<body>
<div id='div1'>div1</div>
<div id='div2'>div2</div>
<div id='div3'>div3</div>

<script>
let testString = '';

const handleMoveListener = (e) => { 
  e.preventDefault();
  e.stopPropagation();
  
  let targetElement;
  // 区分鼠标事件和触摸事件
  if (e.type === 'touchmove') {
    // 获取第一个触摸点的视口坐标
    const touch = e.touches[0];
    // 根据坐标定位当前元素
    targetElement = document.elementFromPoint(touch.clientX, touch.clientY);
  } else {
    // 鼠标事件直接使用原生target
    targetElement = e.target;
  }
  
  // 确保元素有id时再拼接,避免报错
  if (targetElement?.id) {
    testString += ' ' + targetElement.id;
  }
}

const handleEndHandler = (e) => {
  alert(testString);
  testString = '';
}

let elementsArray = document.querySelectorAll("div");
elementsArray.forEach(function (elem) {
  elem.addEventListener('mousemove', handleMoveListener);
  elem.addEventListener('touchmove', handleMoveListener);
  elem.addEventListener('mouseup', handleEndHandler);
  elem.addEventListener('touchend', handleEndHandler);
});
</script>
</body>
</html>

关键修改说明

  1. 统一了鼠标和触摸的移动事件处理函数,在内部通过e.type区分事件类型
  2. 针对touchmove事件:通过e.touches[0]获取触摸点的视口坐标,再用document.elementFromPoint(x, y)拿到当前手指下方的元素
  3. 加入了可选链判断targetElement?.id,避免获取到null或非DOM元素时出现报错

额外注意点

  • 如果页面存在滚动,需要加上document.documentElement.scrollTopdocument.documentElement.scrollLeft来修正坐标,确保elementFromPoint定位准确
  • 保留e.preventDefault()可以避免触发浏览器默认触摸行为(如页面滚动),防止干扰事件触发

内容的提问来源于stack exchange,提问作者Mahesh

火山引擎 最新活动