单击标签元素内的文本时,Javascript 事件侦听器会触发两次

Kla*_*vic 3 javascript label addeventlistener

单击标签内的文本时,如何使函数不触发两次。

如果我使用 event.preventDefault() 则用于选中复选框的基本浏览器功能也将停止工作。

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

label.addEventListener('click', handleLabelClick);

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

T.J*_*der 5

据我了解,您希望点击.parent元素来触发点击处理程序,但您不希望该处理程序因与复选框或其标签相关的点击而被触发.parent

有两种方法可以做到这一点:

  1. label为该调用添加处理程序stopPropagation,或

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

这是方法#1:

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');
}
Run Code Online (Sandbox Code Playgroud)
.parent {
  border: 1px solid #ddd;
}
Run Code Online (Sandbox Code Playgroud)
<div class="parent">
  <label for="option1">
    <span>Select me</span>
    <input id="option1" type="checkbox">
  </label>
</div>
Run Code Online (Sandbox Code Playgroud)

这是方法#2:

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');
}
Run Code Online (Sandbox Code Playgroud)
.parent {
  border: 1px solid #ddd;
}
Run Code Online (Sandbox Code Playgroud)
<div class="parent">
  <label for="option1">
    <span>Select me</span>
    <input id="option1" type="checkbox">
  </label>
</div>
Run Code Online (Sandbox Code Playgroud)