为什么DOM更改后touchmove事件没有被触发?

4
在将我的应用程序从鼠标事件转换为触摸事件时,我注意到一些奇怪的行为。基本上,在DOM更改后,touchmove停止工作。在同样的情况下,鼠标事件可以正常工作。我使用Chrome开发者工具和Firefox进行了测试,它们似乎对结果达成了一致意见。这是一个错误还是我漏掉了什么?
我创建了一个非常简单的代码示例来证明问题与我使用的任何框架或库都无关。我还发现了似乎相关的问题,但不幸的是其中没有解决方案。
触摸演示:

window.addEventListener("touchmove", onTouchMove, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("touchstart", onTouchStart)
})

function onTouchMove(event) {
  console.log("touch move")
}

function onTouchStart(event) {
  console.log("touch start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

鼠标演示:

window.addEventListener("mousemove", onMouseMove, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("mousedown", onMouseDown)
})

function onMouseMove(event) {
  console.log("mouse move")
}

function onMouseDown(event) {
  console.log("mouse start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

从红色正方形开始的连续拖动手势应该导致以下事件发生:1)日志中出现“start”消息,2)该正方形消失,这是DOM更改的情况,3)在日志中出现“move”消息序列。这在鼠标演示中是如此,但在触摸演示中,正方形消失后没有“move”事件。

你怎么拖动这个正方形?一旦你点击它,它就会消失。 - Barmar
当我点击红色正方形并使其消失后,我仍然看到“触摸移动”消息。 - Barmar
1
这是预期的行为。它应该写入消息并消失。那就是我所指的DOM更改。如果我没有表达清楚,对不起。 - dareka
1
好的,现在我明白了区别。使用触摸时,我必须松开并再次触摸才能开始查看消息。而使用鼠标则不需要释放按钮。 - Barmar
因此,事件不会完全停止工作。 - Barmar
是的。它只在一个连续的拖动手势期间停止工作。也就是说,如果我想用其他东西交换拖动对象。谢谢您的意见,我会更新问题。 - dareka
1个回答

3
这是一种预期行为,如果你删除了元素。
根据文档,如果你删除一个元素,它上面的事件仍然会被触发,并且不一定会冒泡到窗口或文档中。
因此,如果您想删除元素,有两种解决方案。您可以修改“remove”方法,以便它只隐藏元素,直到触摸过程结束,或者您可以将事件附加到目标本身。
下面是一个示例,您可以看到,即使在删除元素后,该元素的touchmove事件仍然出现,而窗口的touchmove事件则不会出现。

window.addEventListener("touchmove", onTouchMoveWindow, {passive: false})

document.addEventListener('DOMContentLoaded', function(){ 
  var elem = document.getElementById("nice");
  console.log(elem)
  elem.addEventListener("touchstart", onTouchStart)
  elem.addEventListener("touchmove", onTouchMoveElement)
})

function onTouchMoveWindow(event) {
  console.log("touch move window")
}

function onTouchMoveElement(event) {
  console.log("touch move element")
}

function onTouchStart(event) {
  console.log("touch start")
  var elem = document.getElementById("nice")
  elem.remove()
}
<!DOCTYPE html>
<html>
<body style="width: 100%; height: 100%; background-color: yellow">
  <div style="position: absolute; width: 100px; height: 100px; background-color: red; left: 100px; top: 100px" id="nice"></div>
</body>
</html>

相关问题:

原始回答:


最近我在自己的脚本中遇到了一个问题,我假设这是一个 bug。我给 body 添加了一个带有 passive: false 选项的 touchmove 事件以 preventDefault,然后将其删除。一旦我删除它,它就会阻止具有 active 的 CSS 类。我花了几个小时来尝试修复它,最终解决方法是在删除第一个函数后立即添加一个新的、***"空白""空函数"***到 touchmove 事件中。非常奇怪。我真的很想知道为什么会发生这种情况。 - oldboy
@oldboy,你能否详细说明一下这个问题? - سعيد

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接