Javascript 单击事件触发两次,即使使用 stopPropagation

Javascript click event firing twice, even with stopPropagation

我有一组这样的物品:

<label for="Cadenza-1" class="cars">
    <input type="checkbox" value="1" alt="Cadenza" id="Cadenza-1" name="vehicles[]">
    <img src="img/bill_murray_173x173.jpg">
    <span>Cadenza</span>
</label>

大约有 13 个。我想在单击时向标签添加 class 。但是,单击事件会触发两次。现在我正在调试点击事件,然后我将添加 class:

var cars = document.getElementsByClassName('cars');

for(var c = 0;c < cars.length; c++){
    cars[c].addEventListener("click", function(e){
        selectVehicle(cars[c],e);
    },false);
}

function selectVehicle(el,e) {
    console.log(e);
    e.stopPropagation();
}

console.log 触发两次。

尝试在 stopPropogation 之后添加 preventDefault:

function selectVehicle(el,e) {
    console.log(e);
    e.stopPropagation();
    e.preventDefault();
}

我认为最好将 console.log(e) 放在 stopPropogation & preventDefault 之后。然后您还需要实现将复选框设置为已选中的功能,因为这可以防止这种情况发生。

<span><img> 接收到 "click" 事件时,这会将 DOM 冒泡到 <label> 元素,并且您的将调用事件处理程序。 <label> 然后在 <input> 元素上触发 另一个 "click" 事件,并且还会冒泡到 <label>.

您可以检查处理程序以查看 <input> 是否被点击:

function selectVehicle(el,e) {
    if (e.target.tagName !== "INPUT") return;

    // do stuff
}

或者,您可以只将 "click" 处理程序添加到 <input> 本身。

现在您还会注意到您的代码无法正常工作,因为您遇到了在循环内绑定事件处理程序的常见问题。问题是当事件处理程序实际 运行 时,变量 c 的值将是 cars 列表的长度。有几种方法可以解决这个问题;一种是使用 forEach() 循环而不是 for 循环:

[].forEach.call(cars, function(car) {
    car.addEventListener("click", function(e){
        selectVehicle(car,e);
    }, false);
});

您正在将事件侦听器添加到标签,您应该将事件侦听器添加到复选框,因为标签行为复制在 for 中指定的相同输入。

请注意,如果您只单击复选框,回调会正常工作,这是因为标签上的事件是由复选框引发的。

正确的做法是只为复选框添加事件侦听器或在 setlectVehicle 回调中添加阻止默认值。

您不需要 preventDefault 或 stopPropagation,只需在输入元素上添加监听器即可。

cars[c].children[0].addEventListener("click", function(e) {

试试这个。它按预期工作。

此外,如果标签元素包含所需的 input/other 元素,则不需要将 ID 与标签一起使用

var cars = document.getElementsByClassName('cars');

for (var c = 0; c < cars.length; c++) {
  cars[c].children[0].addEventListener("click", function(e) {
    selectVehicle(cars[c], e);
  }, false);
}

function selectVehicle(el, e) {
  console.log(e);

}
<label class="cars">
  <input type="checkbox" value="1" alt="Cadenza" name="vehicles[]">
  <img src="img/bill_murray_173x173.jpg">
  <span>Cadenza</span>
</label>
<label class="cars">
  <input type="checkbox" value="1" alt="Cadenza" name="vehicles[]">
  <img src="img/bill_murray_173x173.jpg">
  <span>Cadenza 2</span>
</label>