我用香草JS Tic tac toe玩得很开心每个单元格都是一个按钮。为了处理点击,我在包装div中添加了一个eventListener:
board.addEventListener("click", handleClick, true);
稍后在printWinner()
函数中,我尝试删除它,但没有效果。。。
const printWinner = (winner) => {
// ...
board.removeEventListener("click", handleClick);
}
如何删除此eventListener
?
完整代码:
// Some settings
const symbols = ['X', '0'];
const board = document.querySelector('#board');
// Append a result popup
const results = document.createElement("div");
results.classList.add("message");
document.body.insertBefore(results, board);
// Winning combinations
const combinations = [
[1,2,3],
[4,5,6],
[7,8,9],
[1,4,7],
[2,5,8],
[3,6,9],
[1,5,9],
[7,5,3]
]
// Base variables
let i = 1;
let move= 0;
// Check if there's a winner
const checkWin = () => {
let winner = false;
combinations.forEach(combination => {
let c0 = board.querySelector(`#c${combination[0]}`).innerHTML || undefined;
let c1 = board.querySelector(`#c${combination[1]}`).innerHTML || undefined;
let c2 = board.querySelector(`#c${combination[2]}`).innerHTML || undefined;
if (c0 === c1 && c0 === c2 && c0 !== undefined) {
winner = symbols.indexOf(c0) + 1;
printWinner(winner);
return;
}
});
}
// Cells click handling
const handleClick = (event) => {
if(!event.target.innerHTML && event.target.nodeName == 'BUTTON') {
let currSymbol = move % 2 ? symbols[1] : symbols[0];
event.target.innerHTML = currSymbol;
event.target.setAttribute("disabled", true);
event.preventDefault();
checkWin();
move++;
}
}
// Bind the click handler
board.addEventListener("click", handleClick, true);
// Print the winner
const printWinner = (winner) => {
let winnerMessage = document.createTextNode(`Player ${winner} wins!`);
results.appendChild(winnerMessage);
results.classList.add("is-visible");
setTimeout(() => {
results.classList.remove("is-visible");
}, 4000)
board.removeEventListener("click", handleClick);
}
// Fill the board
(function fillDom() {
let dom = '';
for (let row = 1; row <= 3; row++) {
dom += '<div class="board__row">';
for (let cell = 1; cell <= 3; cell++) {
dom += `<button id="c${i}" class="board__cell"></button>`;
if (cell == 3) {
dom += `</div>`;
}
i++;
}
}
board.innerHTML = dom;
})();
:root {
--bgColor: #fff;
--mainColor: #04e;
--mainColor-hover: #dde7ff;
--mainColor-active: #eef3ff;
--messageColor: #04e;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
padding: 0;
margin: 0;
}
body {
background-color: var(--bgColor);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
font-size: 18px;
line-height: 1.48;
}
.board {
width: 300px;
height: 300px;
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
.board__row {
width: 100%;
border-bottom: 2px solid var(--mainColor);
display: flex
}
.board__row:last-of-type {
border-bottom: 0;
}
.board__cell {
flex: 1 1 auto;
width: 100px;
height: 100px;
text-align: center;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 0;
border-radius: 0;
border-right: 2px solid var(--mainColor);
font-size: 24px;
font-weight: 600;
outline: 0;
cursor: pointer;
color: var(--mainColor);
background-color: var(--bgColor);
transition: background-color 160ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.board__cell:hover {
background-color: var(--mainColor-hover);
}
.board__cell[disabled] {
background-color: var(--mainColor-active);
}
.board__row .board__cell:last-child {
border-right: 0;
}
.message {
position: fixed;
z-index: 1;
top: 0;
left: 50%;
opacity: 0;
transform: translate(-50%, -100px);
transition: all 400ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
color: #fff;
background-color: var(--messageColor);
border-radius: 4px;
padding: 12px 24px;
box-shadow: 0 2px 8px rgba(0,0,0,.16)
}
.message.is-visible {
opacity: 1;
transform: translate( -50%, 24px);
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
<div id="board" class="board"></div>
或者在代码笔上看到它。
问题在于如何使用"捕获"标志。
当您设置事件侦听器时,您将其注册为捕获侦听器:
board.addEventListener("click", handleClick, true);
// -----^
但是,当您试图删除它时,您并没有指定一个捕获侦听器:
// Notice the lack of a third argument
board.removeEventListener("click", handleClick);
引用MDN页面:
删除捕获侦听器不会影响同一侦听器的非捕获版本,反之亦然。
因此,您需要指定要删除捕获侦听器:
board.removeEventListener("click", handleClick, true);
更改后的代码:
// Some settings
const symbols = ['X', '0'];
const board = document.querySelector('#board');
// Append a result popup
const results = document.createElement("div");
results.classList.add("message");
document.body.insertBefore(results, board);
// Winning combinations
const combinations = [
[1,2,3],
[4,5,6],
[7,8,9],
[1,4,7],
[2,5,8],
[3,6,9],
[1,5,9],
[7,5,3]
]
// Base variables
let i = 1;
let move= 0;
// Check if there's a winner
const checkWin = () => {
let winner = false;
combinations.forEach(combination => {
let c0 = board.querySelector(`#c${combination[0]}`).innerHTML || undefined;
let c1 = board.querySelector(`#c${combination[1]}`).innerHTML || undefined;
let c2 = board.querySelector(`#c${combination[2]}`).innerHTML || undefined;
if (c0 === c1 && c0 === c2 && c0 !== undefined) {
winner = symbols.indexOf(c0) + 1;
printWinner(winner);
return;
}
});
}
// Cells click handling
const handleClick = (event) => {
if(!event.target.innerHTML && event.target.nodeName == 'BUTTON') {
let currSymbol = move % 2 ? symbols[1] : symbols[0];
event.target.innerHTML = currSymbol;
event.target.setAttribute("disabled", true);
event.preventDefault();
checkWin();
move++;
}
}
// Bind the click handler
board.addEventListener("click", handleClick, true);
// Print the winner
const printWinner = (winner) => {
let winnerMessage = document.createTextNode(`Player ${winner} wins!`);
results.appendChild(winnerMessage);
results.classList.add("is-visible");
setTimeout(() => {
results.classList.remove("is-visible");
}, 4000)
board.removeEventListener("click", handleClick, true);
}
// Fill the board
(function fillDom() {
let dom = '';
for (let row = 1; row <= 3; row++) {
dom += '<div class="board__row">';
for (let cell = 1; cell <= 3; cell++) {
dom += `<button id="c${i}" class="board__cell"></button>`;
if (cell == 3) {
dom += `</div>`;
}
i++;
}
}
board.innerHTML = dom;
})();
:root {
--bgColor: #fff;
--mainColor: #04e;
--mainColor-hover: #dde7ff;
--mainColor-active: #eef3ff;
--messageColor: #04e;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
padding: 0;
margin: 0;
}
body {
background-color: var(--bgColor);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
font-size: 18px;
line-height: 1.48;
}
.board {
width: 300px;
height: 300px;
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
}
.board__row {
width: 100%;
border-bottom: 2px solid var(--mainColor);
display: flex
}
.board__row:last-of-type {
border-bottom: 0;
}
.board__cell {
flex: 1 1 auto;
width: 100px;
height: 100px;
text-align: center;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 0;
border-radius: 0;
border-right: 2px solid var(--mainColor);
font-size: 24px;
font-weight: 600;
outline: 0;
cursor: pointer;
color: var(--mainColor);
background-color: var(--bgColor);
transition: background-color 160ms cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.board__cell:hover {
background-color: var(--mainColor-hover);
}
.board__cell[disabled] {
background-color: var(--mainColor-active);
}
.board__row .board__cell:last-child {
border-right: 0;
}
.message {
position: fixed;
z-index: 1;
top: 0;
left: 50%;
opacity: 0;
transform: translate(-50%, -100px);
transition: all 400ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
color: #fff;
background-color: var(--messageColor);
border-radius: 4px;
padding: 12px 24px;
box-shadow: 0 2px 8px rgba(0,0,0,.16)
}
.message.is-visible {
opacity: 1;
transform: translate( -50%, 24px);
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
<div id="board" class="board"></div>