在 div 中使用 setPointerCapture 指针向下并释放按钮后触发按钮单击事件 - 为什么?

问题描述 投票:0回答:1

我有一个简单的网页,带有

button
div
button
有一个
click
事件侦听器,单击时会记录到控制台。
div
有一个
pointerdown
事件监听器,它调用
setPointerCapture
来捕获指针事件。

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=devicexx-width, initial-scale=1.0" />
  <title>play</title>
</head>
<body>

<button id="btn">Test</button>
<div id="div" style="margin-top: 20px; height: 50px; width: 50px; background: red"></div>

<script>
  const btn = document.getElementById("btn");
  btn.addEventListener("click", () => console.log("btn clicked"));

  const div = document.getElementById("div");
  div.addEventListener("pointerdown", (e) => {
    e.target.setPointerCapture(e.pointerId);
  });
</script>

</body>
</html>

在 Firefox 上,当我在

div
上按鼠标,将其拖动到
button
上并在
button
上释放鼠标时,
button
click
事件会触发。此问题在 Edge、Safari 和 Chrome 上不会发生。

我想知道为什么会发生这种情况?如何防止

click
事件触发?

我尝试在指针向上时手动删除该指针捕获,如下所示:

div.addEventListener("pointerup", (e) => {
  e.target.releasePointerCapture(e.pointerId);
});

这没有帮助。

PS:如果你想知道我为什么要阻止它,那是因为它与这个问题有关:https://github.com/radix-ui/primitives/issues/2777.

javascript html typescript firefox dom-events
1个回答
0
投票

我相信你已经发现了一个错误。

单击事件是同一元素上的鼠标/指针向下和鼠标/指针向上。

让我们稍微更改一下您的代码。

<!DOCTYPE html><html lang="en"><head>
  <title>play</title>
</head><body>
<button id="btn">Test</button>
<div id="div" style="margin-top: 20px; height: 50px; width: 50px; background: red"></div>
<script>
  function report( e ) {
    console.log( this.tagName, e.target.tagName, e.type );
  }

  const btn = document.getElementById("btn");
  btn.addEventListener( 'click',       report );
  btn.addEventListener( 'pointerdown', report );
  btn.addEventListener( 'pointerup',   report );

  const div = document.getElementById( 'div' );
  div.addEventListener( 'pointerdown', ( e ) => {
    console.log( 'DIV', e.target.tagName, e.type );
    e.target.setPointerCapture( e.pointerId );
  } );
  div.addEventListener( 'pointerup', report );
  div.addEventListener( 'click',     report );

  document.body.addEventListener( 'pointerdown', report );
  document.body.addEventListener( 'pointerup',   report );
  document.body.addEventListener( 'click',       report );
</script>
</body></html>

上面的代码允许尝试各种事情。例如

  1. 向下并按住 div,然后向上拖动到右侧(主体),可以正确地将向上事件的目标定向到 div,就像在那里捕获的指针事件一样。因为 div 上的向下事件向上冒泡到主体,所以主体上有一个点击。 (我承认我不太确定为什么div上的down和captured up不是div上的点击。我认为应该是。)
  2. 向下并按住主体,然后在 div 上向上拖动,可以正确地将向上事件的目标报告为 div,因为这就是向上事件发生的位置。向上事件冒泡到主体,因此主体上有一个点击事件。
  3. 同样向下并按住主体,然后向上拖动到按钮,正确地将向上事件的目标报告为按钮。向上事件再次冒泡,因此主体上有一个点击。
  4. 但是,向下并按住 div,然后向上拖动到按钮,会正确地报告 div 上的向上事件,但 Firefox 似乎也混淆了向下和(捕获的)向上事件发生在同一个事件上元素(div),但指针位于按钮上方。按钮上不应该有点击事件。

它可能与Bugzilla 1610659有关,但这里的测试与该错误不同。这是你的错误。你应该归档。

© www.soinside.com 2019 - 2024. All rights reserved.