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

dcp*_*450 1 javascript addeventlistener

我有一组这样的项目:

<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>
Run Code Online (Sandbox Code Playgroud)

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

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();
}
Run Code Online (Sandbox Code Playgroud)

console.log闪光两次。

mat*_*rer 7

尝试在 stopPropogation 之后添加 preventDefault:

function selectVehicle(el,e) {
    console.log(e);
    e.stopPropagation();
    e.preventDefault();
}
Run Code Online (Sandbox Code Playgroud)

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


Poi*_*nty 7

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

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

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

    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以仅将“单击”处理程序添加到其<input>本身。

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

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