繁体   English   中英

如何让事件侦听器只触发一次?

[英]How can I make an event listener fire only once?

我正在用 6 张卡片构建一个非常简单的记忆匹配游戏。 每张卡片都在一个.card类的div ,该div包含另外两个div元素 - 卡片的正面(只是一个简单的绿色背景 img)和卡片的背面(我选择的随机图像)。

背面在此处输入图片说明

正面在此处输入图片说明

每张卡片都有一个点击事件监听器。 单击卡片后,卡片将从背面旋转到正面并显示图像。 如果您选择的两张图片匹配,您会收到 +1 Score 如果您选择的图像碰巧不匹配,则所有卡片都会旋转到其背面,您会收到“失败”+1,并且您输掉了游戏。

主要问题是由于事件侦听器,我可以一遍又一遍地单击和旋转一张卡片。 有没有办法让它只火一次? 我曾尝试在事件侦听器上使用once: true但这导致即使在输掉游戏后卡片也无法点击,因此我已将其删除。

 const cards = document.querySelectorAll(".card"); const images = document.querySelectorAll("img"); let scoreElement = document.getElementById("score"); let failsElement = document.getElementById("fails"); let failsAmount = 0; let scoreAmount = 0; let pickedCards = []; function pickCards() { // Iterate through every div with the class of ".card" for (let i = 0; i < cards.length; i++) { // Add an event listener to them cards[i].addEventListener("click", function() { // Rotate the card cards[i].classList.toggle("flipcard"); // After clicking on the card that contains the img, push the img into the pickedCards array. pickedCards.push(images[i]); checkForMatch(); }); } } function checkForMatch() { // Check the source of the images from the array if (pickedCards[0].src == pickedCards[1].src) { alert("Match! +1 score"); scoreAmount++; scoreElement.textContent = "Score: " + scoreAmount; // Empty the array so the player can pick another 2 cards pickedCards = []; } else { hideCards(); alert("Not a match! Sorry!"); failsAmount++; failsElement.textContent = "Fails: " + failsAmount; pickedCards = []; } } function hideCards() { for (let i = 0; i < cards.length; i++) { setTimeout(function() { // Remove the flipcard class from the cards and show the front face again. cards[i].classList.remove("flipcard"); }, 1000); } } pickCards();
 * { padding: 0; margin: 0; } *, *:before, *:after { box-sizing: inherit; } html { box-sizing: border-box; } html,body { height: 100%; } .card-container { display: flex; position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); perspective: 1200; } .flipcard { transform: rotateY(-180deg); } .card { width: 200px; height: 200px; transition: all 0.7s; transform-style: preserve-3d; margin: 0em 1em; } .front-card, .back-card { width: 200px; height: 200px; position: absolute; top: 0; left: 0; backface-visibility: hidden; } .front-card { background: url("./IMGs/block.jpg") no-repeat center/cover; } .back-card { transform: rotateY(-180deg); } .back-card img { width: 200px; height: 200px; } #score, #fails { font-size: 2em; }
 <div class="card-container"> <div class="card"> <div class="front-card"></div> <div id="card1" class="back-card"><img src="IMGs/eric.jpg" alt=""></div> </div> <div class="card"> <div class="front-card"></div> <div id="card2" class="back-card"><img src="IMGs/john.webp" alt=""></div> </div> <div class="card"> <div class="front-card"></div> <div id="card3" class="back-card"><img src="IMGs/salim.png" alt=""></div> </div> <div class="card"> <div class="front-card"></div> <div id="card4" class="back-card"><img src="IMGs/salim.png" alt=""></div> </div> <div class="card"> <div class="front-card"></div> <div id="card5" class="back-card"><img src="IMGs/eric.jpg" alt=""></div> </div> <div class="card"> <div class="front-card"></div> <div id="card6" class="back-card"><img src="IMGs/john.webp" alt=""></div> </div> </div> <p id="score">Score: 0</p> <p id="fails">Fails: 0</p>

我还是新手,所以任何提示都将得到认可,谢谢。

对于您的情况,只需在翻转和检查匹配之前添加一个 if 语句:

cards[i].addEventListener('click', function () {
  if (!cards[i].classList.contains('flipcard')) {
     cards[i].classList.toggle('flipcard')
     pickedCards.push(images[i])
     checkForMatch()
  }
})

如果您委托,您可以进行比关闭事件处理程序更好的测试

document.querySelector(".card-container").addEventListener("click", function(e) {
  const tgt = e.target.closest("div");
  if (tgt && tgt.classList.contains("card")) {
    if (tgt.classList.contains("clicked")) return;
    tgt.classList.add("clicked");
    .... // rest of handling here
  }
})

这很容易解决。

  1. 创建一个数组或变量以检查是否单击了相应的卡片。 例子:

    cardClicked = [假,假,假,假,假,假];

  2. 在点击事件上,将选中的cardsClicked[n] 修改为true。 并且,检查(如果)所选卡已被选中。

就是这样。

暂无
暂无

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

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