当点击标签元素内的文本时,Javascript事件监听器会触发两次。

3
如何在单击标签内的文本时使函数不触发两次。
如果我使用event.preventDefault(),那么基本的浏览器功能将无法正常工作,无法选中复选框。

const label = document.querySelector('.parent');

label.addEventListener('click', handleLabelClick);

function handleLabelClick(event) {
  console.log('Clicked')
}
<div class="parent">
  <label for="option1">
    <span>Select me</span>
    <input id="option1" type="checkbox">
  </label>
</div>

2个回答

6
我理解您希望在单击 .parent 元素时触发单击处理程序,但不希望该处理程序针对与位于 .parent 内的复选框或其标签相关的单击事件生效。
有两种方法可以做到这一点:
  1. label 添加处理程序,并调用 stopPropagation,或者

  2. 在事件处理程序内检查事件是否通过了 label

以下是第一种方法的示例代码:

const parent = document.querySelector('.parent');

parent.addEventListener('click', handleLabelClick);

// Stop clicks in the label or checkbox from propagating to parent
parent.querySelector("label").addEventListener("click", function(event) {
  event.stopPropagation();
});

function handleLabelClick(event) {
 console.log('Clicked');
}
.parent {
  border: 1px solid #ddd;
}
<div class="parent">
  <label for="option1">
    <span>Select me</span>
    <input id="option1" type="checkbox">
  </label>
</div>

以下是第二种方法:

const parent = document.querySelector('.parent');

parent.addEventListener('click', handleLabelClick);

function handleLabelClick(event) {
  const label = event.target.closest("label");
  if (label && this.contains(label)) {
    // Ignore this click
    return;
  }
 console.log('Clicked');
}
.parent {
  border: 1px solid #ddd;
}
<div class="parent">
  <label for="option1">
    <span>Select me</span>
    <input id="option1" type="checkbox">
  </label>
</div>


@KlaudioMilankovic - 很抱歉,我不明白你在描述什么。 - T.J. Crowder
1
所以,假设<label for="option1" class="test"> <span>选择我</span> <input id="option1" type="checkbox"> </label> 是一个独立的组件,你将其放置在名为“parent”的其他组件中。一旦你将事件监听器附加到父级并单击标签,它会触发两次而不是一次。我试图不处理标签上的点击事件,因为这是由浏览器完成的。 - Klaudio Milankovic
@KlaudioMilankovic - 我想我明白了。所以在你的例子中,你希望 handleLabelClick 在与复选框无关的点击时触发,而不是在与复选框相关的点击时触发? - T.J. Crowder
1
没错。我想保留复选框的默认浏览器功能,但不要让它触发两次附加到父级的函数。 - Klaudio Milankovic
@KlaudioMilankovic - 不错的交易。我已经更新了答案。 - T.J. Crowder
选项1是解决我的问题的方案。非常感谢! - LReeder14

2
这是一种标准(不幸的)浏览器行为。
属性 `for` 将 `

谢谢 @papo!我刚刚问了一个类似的问题,实际上是因为观察到这种行为。你对“为什么”的解释让我明白了事情的来龙去脉。 - Daniel Brady

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