为什么事件侦听器没有被删除

Why event listeners are not getting removed

document.getElementsByClassName('restart')[0].addEventListener('click', init);
var tiles = document.querySelectorAll('.row div');
let bombTile = [];

init();


 function clickHand(tile, index) {
    if (bombTile.indexOf(index) !== -1) {
        bombClicked(tile , index);
    } else {
        flipMe(tile, index);
    }
}


function bombClicked(tile ,index) {
    tile.classList.add('bomb');
    bombTile.forEach(e => {
        tiles[e].classList.add('bomb');
        tiles[e].innerHTML = '<i class="fas fa-bomb"></i>';
    })
    document.getElementsByClassName('row')[0].classList.add('bombed');
    
}

function flipMe(tile , index) {
    tile.classList.add('active');
    tile.innerHTML = '<i class="fas fa-sun"></i>';
    tile.removeEventListener('click' , clickHand);
}


function init() {
    bombTile = []
    while (bombTile.length < 10) {
        var r = Math.floor(Math.random() * 80) + 1;
        if (bombTile.indexOf(r) === -1) bombTile.push(r);
    }
    document.getElementsByClassName('row')[0].classList.remove('bombed')
    tiles.forEach((tile, index) => {
        tile.addEventListener('click',  clickHand.bind(this,tile , index));
        tile.className = '';
        tile.innerHTML = '';

    })
}
*{
    padding: 0;
    margin: 0;
}

body{
    display: flex;
    justify-content: center;
    flex-direction: column;
    background-image: linear-gradient(to right, rgba(233,233,233,.9), rgba(0,0,0,.8)) , url("https://images5.alphacoders.com/540/thumb-1920-540654.jpg");
    background-size: cover;
    align-items: center;
    font-family: 'Montserrat', sans-serif;
    min-height: 100vh;
}

.row{
    width: 540px;
    display: flex;
    flex-wrap: wrap;
    box-shadow:0 2px 4px rgba(0,0,0,.8);
}

.row.bombed{
    animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
    transform: translate3d(0, 0, 0);
    backface-visibility: hidden;
}

h1{
    margin-bottom: 20px;
    font-weight: 300;
}

.row div{
    display: flex;
    justify-content: center;
    box-sizing: border-box;
    align-items: center;
    width: 60px;
    height: 60px;
    background: rgba(200,200,200,.8);
    border: 1px solid #000;

    transition: all .3s ease;

}

.row div.active{
    transform: rotateY(180deg);
    background-color: #000;
}

.row div.active i{
    color: yellow;
    font-size: 30px;
}

.row div.bomb{
    transform: rotateY(180deg);
    background: #f00;
    font-size: 20px;
}


.restart:link,
.restart:visited{
    text-decoration: none;
    text-transform: uppercase;
    padding: 10px 15px;
    display: inline-block;
    margin: 20px 0;
    border: 1px solid #fff;
    color: white;
    transition: all .3s ease;
}

.restart:hover{
    border: 1px solid #fff;
    background-color: white;
    color: black;
}

@keyframes shake {
    10%, 90% {
      transform: translate3d(-1px, 0, 0);
    }
    
    20%, 80% {
      transform: translate3d(2px, 0, 0);
    }
  
    30%, 50%, 70% {
      transform: translate3d(-4px, 0, 0);
    }
  
    40%, 60% {
      transform: translate3d(4px, 0, 0);
    }
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bomber</title>
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
    <script src="https://kit.fontawesome.com/f80fd99102.js" crossorigin="anonymous"></script>
</head>
<body> 
    <h1>
        Bomber
    </h1>
    <div class="bomber-grid">
        <div class="row">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
        </div>
    </div>
    <a href="#!" class="restart">
        New Game
    </a>
    <script src="index.js"></script>
</body>
</html>

这是一个简单的炸弹游戏,其中 10 个方块中有炸弹。一旦用户点击炸弹游戏结束。

我的问题是,当我单击任何图块时,我想删除附加到它的事件侦听。如果用户单击带有炸弹的图块,我想从每个图块中删除事件侦听器。

我添加了删除事件侦听器的代码,但它无法正常工作。

要删除事件侦听器,您必须将 相同的 函数传递给 removeEventListener,您传递给 addEventListener

tile.removeEventListener('click' , clickHand);

tile.addEventListener('click',  clickHand.bind(this,tile , index));

您正在尝试删除 clickHand,但您添加了一个 new 函数,该函数是通过在 clickHand 上调用 bind 生成的。


一个更简单的方法可能是更改 clickHand 以便它检查图块的状态并确定它是否已被单击(如果已单击则返回而不做任何其他事情)。

removeListener 可能不起作用的原因是您每次使用 .bind 时都在创建一个新函数。 removeEventListener 期望在 addEventListener 中用作处理程序的函数相同。

你正在做的是,

tile.addEventListener('click',  clickHand.bind(this,tile , index));

因此您无法使用

删除
tile.removeEventListener('click',  clickHand);

要正确删除它,请执行以下操作,

let tileHandler =  clickHand.bind(this,tile , index)
tile.addEventListener('click',  tileHandler);

// Then remove by
tile.removeEventListener('click',  tileHandler);

但是有很多图块,您必须为每个创建的新处理程序保留一个记录。所以你能做的就是有一个标志来判断游戏是否结束。如果是,则防止瓷砖翻转。

添加一个标志

let gameOver;

在您的点击函数中

else if(!gameOver){
        flipMe(tile, index);
    }
}

并在您的 bombClicked() 函数中添加

gameOver=true;

document.getElementsByClassName('restart')[0].addEventListener('click', init);
var tiles = document.querySelectorAll('.row div');
let bombTile = [];
let gameOver = false;
init();


 function clickHand(tile, index) {
    if (bombTile.indexOf(index) !== -1) {
        bombClicked(tile , index);
    } else if(!gameOver){
        flipMe(tile, index);
    }
}


function bombClicked(tile ,index) {
    gameOver=true;
    tile.classList.add('bomb');
    bombTile.forEach(e => {
        tiles[e].classList.add('bomb');
        tiles[e].innerHTML = '<i class="fas fa-bomb"></i>';
    })
    document.getElementsByClassName('row')[0].classList.add('bombed');
    
}

function flipMe(tile , index) {
    tile.classList.add('active');
    tile.innerHTML = '<i class="fas fa-sun"></i>';
    tile.removeEventListener('click' , clickHand);
}


function init() {
    bombTile = []
    while (bombTile.length < 10) {
        var r = Math.floor(Math.random() * 80) + 1;
        if (bombTile.indexOf(r) === -1) bombTile.push(r);
    }
    document.getElementsByClassName('row')[0].classList.remove('bombed')
    tiles.forEach((tile, index) => {
        tile.addEventListener('click',  clickHand.bind(this,tile , index));
        tile.className = '';
        tile.innerHTML = '';

    })
}
*{
    padding: 0;
    margin: 0;
}

body{
    display: flex;
    justify-content: center;
    flex-direction: column;
    background-image: linear-gradient(to right, rgba(233,233,233,.9), rgba(0,0,0,.8)) , url("https://images5.alphacoders.com/540/thumb-1920-540654.jpg");
    background-size: cover;
    align-items: center;
    font-family: 'Montserrat', sans-serif;
    min-height: 100vh;
}

.row{
    width: 540px;
    display: flex;
    flex-wrap: wrap;
    box-shadow:0 2px 4px rgba(0,0,0,.8);
}

.row.bombed{
    animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
    transform: translate3d(0, 0, 0);
    backface-visibility: hidden;
}

h1{
    margin-bottom: 20px;
    font-weight: 300;
}

.row div{
    display: flex;
    justify-content: center;
    box-sizing: border-box;
    align-items: center;
    width: 60px;
    height: 60px;
    background: rgba(200,200,200,.8);
    border: 1px solid #000;

    transition: all .3s ease;

}

.row div.active{
    transform: rotateY(180deg);
    background-color: #000;
}

.row div.active i{
    color: yellow;
    font-size: 30px;
}

.row div.bomb{
    transform: rotateY(180deg);
    background: #f00;
    font-size: 20px;
}


.restart:link,
.restart:visited{
    text-decoration: none;
    text-transform: uppercase;
    padding: 10px 15px;
    display: inline-block;
    margin: 20px 0;
    border: 1px solid #fff;
    color: white;
    transition: all .3s ease;
}

.restart:hover{
    border: 1px solid #fff;
    background-color: white;
    color: black;
}

@keyframes shake {
    10%, 90% {
      transform: translate3d(-1px, 0, 0);
    }
    
    20%, 80% {
      transform: translate3d(2px, 0, 0);
    }
  
    30%, 50%, 70% {
      transform: translate3d(-4px, 0, 0);
    }
  
    40%, 60% {
      transform: translate3d(4px, 0, 0);
    }
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bomber</title>
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
    <script src="https://kit.fontawesome.com/f80fd99102.js" crossorigin="anonymous"></script>
</head>
<body> 
    <h1>
        Bomber
    </h1>
    <div class="bomber-grid">
        <div class="row">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
        </div>
    </div>
    <a href="#!" class="restart">
        New Game
    </a>
    <script src="index.js"></script>
</body>
</html>