javascript - 如何让事件监听器只触发一次?
问题描述
我正在用 6 张卡片构建一个非常简单的记忆匹配游戏。每张卡片都在一个包含另外两个元素div
的类中- 卡片的正面(只是一个简单的绿色背景 img)和卡片的背面(我选择的随机图像)。.card
div
每张卡片都有一个点击事件监听器。单击卡片后,卡片会从背面旋转到正面并显示图像。如果您选择的两张图片匹配,您将获得 +1分数。如果您选择的图像不匹配,则所有卡片都会旋转到它们的背面,并且您会收到 +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>
我还是新手,所以任何提示都会受到欢迎,谢谢。
解决方案
如果你委托你可以测试比关闭事件处理程序更好
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
}
})
推荐阅读
- regex - 正则表达式选择零前缀以避免负前瞻
- python - 如何使用多个索引多次拆分 numpy 数组?
- java - 获取 java.lang.NoClassDefFoundError: jcifs/smb/NtlmPasswordAuthentication 错误
- java - 从 MongoDb 删除条目时,不会触发 AbstractMongoEventListener 的 AfterDeleteEvent
- java - 我应该关心 File#separator for Path#resolve(String)
- python - 在二进制字符串中查找子字符串
- delphi - Delphi Win32 TXMLDocument 不能从线程中实例化和使用?
- flutter - iOS Simulator 部署目标设置为 8.0,但支持的部署目标版本范围为 9.0 到 15.0.99
- javascript - 如何导入从 html 导入 .json 的 .js
- c# - API 请求中不支持的接口类型的反序列化