gpt4 book ai didi

javascript - 使用 Vanilla JS 将事件和函数附加到动态元素

转载 作者:行者123 更新时间:2023-11-28 00:08:47 25 4
gpt4 key购买 nike

我创建了简单难度下有 12 张卡片的内存卡游戏,我想通过创建新的动态元素来添加更多卡片,并在我更改难度时将其附加到游戏容器。

使用此代码,我希望新创建的元素具有 flipCard() 函数,当我单击它时它将翻转卡片。然而,这不起作用,每当我点击卡片时,它都会给我一个错误

'TypeError: this.classlist is undefined'(flipCard 函数内部的错误)

game.addEventListener('click', function (e) {
if (e.target) {
flipCard();
}
});

下面的代码可以工作,但不适用于动态元素。

 cards.forEach(card => {
cardCount.push(card);
card.addEventListener('click', flipCard);
});

window.onload = function() {
const game = document.querySelector('.game');
const cards = document.querySelectorAll('.card');
const scoreboard = document.querySelector('.score');
const move = document.querySelector('.move');
const difficulties = document.getElementById("difficulties");

let isCardFlipped = false,
lockBoard = false,
firstCard,
secondCard,
score = 0,
moves = 0,
unflipTimeout = 1500,
cardCount = [];



difficulties.addEventListener("change", function() {
resetGame();
});



function addCard() {
for (i = 0; i < 4; i++) {
game.innerHTML += "<div class='card'>" + "<img src='assets/image/default/bellsprout.svg' class='front-face'>" +
"<img src='assets/image/default/pokeball.svg' class='back-face'>" + "</div>";
}
};

// ATTACH CLICK EVENT AND flipCard() FUNCTION FOR EVERY CARD.
// THIS DOESN'T WORK FOR DYNAMICALLY CREATED ELEMENT

// cards.forEach(card => {
// cardCount.push(card);
// card.addEventListener('click', flipCard);
// });

// ATTACH CLICK EVENT AND flipCard() FUNCTION FOR EVERY CARD.
// THIS WILL WORK FOR DYNAMICALLY CREATED ELEMENT,
// BUT "this." INSIDE flipCard() function is not defined/initialize


game.addEventListener('click', function(e) {

if (e.target) {
flipCard();
}

});



// Difficulty Option
(difficulty = () => {
let selected = difficulties.options[difficulties.selectedIndex].value;

if (selected === 'easy') {
unflipTimeout = 1500;
} else if (selected === 'hard') {
unflipTimeout = 500;
// ADD MORE CARD ONLY IF HARD DIFFICULTY IS SELECTED
addCard();
}
})();

// flip card when card is clicked
function flipCard() {
if (lockBoard || this === firstCard) return;
this.classList.add('flip');

if (!isCardFlipped) {
isCardFlipped = true;
firstCard = this;

return;
}

isCardFlipped = false;
secondCard = this;

checkForMatch();
}

// check if 2 selected card are match.
checkForMatch = () => {
// if matched disabled card function, unflip card if not matched.
let isMatch = firstCard.dataset.pokemon ===
secondCard.dataset.pokemon;

isMatch ? disableCard() : unflipCard(unflipTimeout);
}

// disable flip card function
disableCard = () => {
moves++;
score++;
updateScore();

firstCard.removeEventListener('click', flipCard);
secondCard.removeEventListener('click', flipCard);
}

unflipCard = (timeout) => {
lockBoard = true;

moves++;
updateScore();
setTimeout(() => {

firstCard.classList.remove('flip');
secondCard.classList.remove('flip');

resetBoard();
}, timeout);
}

resetBoard = () => {
[isCardFlipped, lockBoard] = [false, false];
[firstCard, secondCard] = [null, null];
}

resetGame = () => {
if (moves > 0) {
var confirm = window.confirm("Changes will be applied after reset \n \n \t \t Reset The Game?");
if (confirm === true) {
score = 0;
moves = 0;
updateScore();

for (var i = 0; i < cardCount.length; i++) {
cardCount[i].classList.remove('flip');
}

alert('Game Restarted! \n \n \t Card Reshuffle.');
shuffle();
} else return;
}
}

var shuffle;
(shuffle = () => {
cards.forEach(card => {
let randomPos = Math.round(Math.random() * cardCount.length);
card.style.order = randomPos;
});
})();

updateScore = () => {
scoreboard.innerText = score;
move.innerText = moves;

if (score === cardCount.length / 2) {
alert("You Win!");
}
}
};
.scoreboard {
display: flex;
flex-flow: row nowrap;
justify-content: space-around;
align-items: center;
padding: 2px;
border-radius: 5px;
background: #363636;
color: #0a8ec2;
}

.scoreboard h1 {
font-size: 1.5rem;
}

.game {
width: 580px;
height: 580px;
margin: auto;
display: flex;
flex-wrap: wrap;
perspective: 1000px;
position: relative;
}

.game .card {
position: relative;
width: calc(25% - 10px);
height: calc(33.333% - 10px);
margin: 5px;
transform-style: preserve-3d;
transition: transform 500ms linear;
}

.game .card.active {
transform: scale(0.97);
}

.game .card.flip {
transform: rotateY(180deg);
}

.game .card .front-face,
.game .card .back-face {
width: 100%;
height: 100%;
position: absolute;
border-radius: 5px;
padding: 20px;
background: #363636;
backface-visibility: hidden;
}

.game .card .front-face {
transform: rotateY(180deg);
backface-visibility: visible;
}
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="assets/css/styles.css">
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/main.js"></script>
<script src="assets/js/app.js"></script>
<title>Memory Card Game</title>
</head>

<body>



<section class="scoreboard">
<h1>Score: <span class="score">0</span> <br> Moves: <span class="move">0</span></h1>
<select id="difficulties" name="difficulties">
<option value="default" disabled>Select Difficulty</option>
<option value="easy" selected>Easy</option>
<option value="hard">Hard</option>
</select>
</section>


<main class="game">
<div class="card" data-pokemon="rattata">
<img src="assets/image/default/rattata.svg" alt="Rattata" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="rattata">
<img src="assets/image/default/rattata.svg" alt="Rattata" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="meowth">
<img src="assets/image/default/meowth.svg" alt="Meowth" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="meowth">
<img src="assets/image/default/meowth.svg" alt="Meowth" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mew">
<img src="assets/image/default/mew.svg" alt="Mew" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mew">
<img src="assets/image/default/mew.svg" alt="Mew" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mankey">
<img src="assets/image/default/mankey.svg" alt="Mankey" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="mankey">
<img src="assets/image/default/mankey.svg" alt="Mankey" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="venonat">
<img src="assets/image/default/venonat.svg" alt="Venonat" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="venonat">
<img src="assets/image/default/venonat.svg" alt="Venonat" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="psyduck">
<img src="assets/image/default/psyduck.svg" alt="Psyduck" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
<div class="card" data-pokemon="psyduck">
<img src="assets/image/default/psyduck.svg" alt="Psyduck" class="front-face">
<img src="assets/image/default/pokeball.svg" alt="Pokemon" class="back-face">
</div>
</main>

</body>

</html>

最佳答案

代替这个:

if (e.target) {
flipCard();
}

这样做:

if (e.target) {
flipCard.bind(this)();
}

将其添加到点击监听器中。 flipCard 函数中的 this 指向 window

关于javascript - 使用 Vanilla JS 将事件和函数附加到动态元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55532701/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com