简体   繁体   English

第一次点击后禁用点击事件

[英]Disable an on click event after the first click

I have a function that counts every time a user clicks on and image on the page:我有一个功能,每次用户点击页面上的图像时都会计数:

for(var i = 0; i < document.getElementsByClassName("face").length; i++){
    document.getElementsByClassName("face")[i].addEventListener("click", counter)
}

function counter(){
    count ++;
}

And I want to disable it after the first click so it won't keep counting duplicate clicks of the same picture.我想在第一次点击后禁用它,这样它就不会继续计算同一张图片的重复点击次数。 I know adding this.onclick=null on the HTML tag will work, but I'm wondering if there a way to do this on the javascript file itself so I don't need to put javascript onto my HTML file.我知道在 HTML 标签上添加this.onclick=null会起作用,但我想知道是否有办法在 javascript 文件本身上执行此操作,因此我不需要将 javascript 放入我的 HTML 文件中。

You need to remove event listener from each clicked element:您需要从每个单击的元素中删除事件侦听器:

function counter(){
    count++;
    this.removeEventListener('click', counter);
}

If you don't want to remove the event (in case you need it reactivated again later or something), you can make count an array of booleans, and each button will flip the value of its own index.如果您不想删除该事件(以防您稍后需要再次重新激活它或其他什么),您可以让count一个布尔值数组,每个按钮将翻转其自己索引的值。 No duplicates that way and you would still be able to easily get the sum of all true flags.这样没有重复,您仍然可以轻松获得所有真实标志的总和。

var count = [];
function counter(i){
    count[i] = true;
}

Quick live example:快速现场示例:

 var count = []; var faces = document.getElementsByClassName("face"); var result = document.getElementById('t'); for(var i = 0; i < faces.length; i++){ handle(i); } function counter(i){ var total = 0; count[i] = true; count.concat([]).reduce(function(p, c){c ? total++ : ''}, 0); result.textContent = total; } function handle(i){ faces[i].addEventListener("click", function(){ counter(i); this.className = 'face clicked'; }) }
 button {width: 50px; height: 50px} button.clicked {opacity: 0.2}
 <button class="face"></button> <button class="face"></button> <button class="face"></button> <button class="face"></button> <p>Count: <span id="t">0</span></p>

There is a neater way to handle the functionality you seek.有一种更简洁的方法来处理您所寻求的功能。 I think what you want is a list of the images that have been clicked like @Shomz thinks as well.我认为您想要的是像@Shomz 认为的那样点击的图像列表。 Is that correct?那是对的吗?

1) The length property of the for loop is evaluated each iteration in the loop. 1) for 循环的长度属性在循环中的每次迭代中进行评估。 Fetching the element from the DOM again with the index i on each iteration is slow.在每次迭代中再次从 DOM 中获取索引为i的元素很慢。

for(var i = 0; i < document.getElementsByClassName("face").length; i++){
    document.getElementsByClassName("face")[i].addEventListener("click", counter)
}

An improvement is to change it into this:一个改进是把它改成这样:

var faces = document.getElementsByClassName("face");
for (var i = 0, var len = faces.length; i < len; i++) {
    faces[i].addEventListener("click", counter)
}

2) But the code still attach an event listener to every single image. 2)但代码仍然为每个图像附加一个事件侦听器。 This is slow if you have many images.如果您有很多图像,这会很慢。 A better way is to let click events bubble upwards and catch them at a parent level.更好的方法是让点击事件向上冒泡并在父级捕获它们。 This is called event delegation .这称为事件委托 This way you don't need a loop, and merely a single event handler needs to be attached.这样您就不需要循环,只需要附加一个事件处理程序。

I store the id of the image, but you could store whatever you need from the node of course that is unique (the src?).我存储图像的 id,但是您可以从节点中存储您需要的任何东西,当然这是唯一的(src?)。

var clickedFaces = [];

document.getElementById('ImageContainer').addEventListener("click", onFaceClick);

function onFaceClick(e) {
    if (e.target.className === 'face' && clickedFaces.indexOf(e.target.id) !== -1) {
        clickedFaces.push(e.target.id);
    }
}

If you want to know how many faces have been clicked:如果你想知道点击了多少张脸:

console.log(clickedFaces.length);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM