javascript - type=button 的 addEventListener 只工作一次
问题描述
我正在做一个作业,用户可以在 n*n 网格内绘制。任务如下:
- 在页面加载时创建一个 16x16 网格作为默认网格
- 为网格实现 mouseover-EventListener,将单元格的背景颜色更改为黑色
- 添加一个重置按钮,询问用户新网格应该有多大
- 添加 2 个按钮,将 mouseover-EventListener(默认黑色)设置为不同的颜色。第一个按钮将颜色变为黄色,第二个按钮变为灰色。
我的问题: 我坚持最后一项任务。2个按钮工作得很好。但是它们只能被调用一次。如果我选择黄色 - 它会绘制黄色。如果我然后选择灰色 - 它会绘制灰色。之后,按钮单击不再执行任何操作,但我仍然可以绘制灰色。
这就是我到目前为止所做的: 首先,我查询选择了按钮类型并添加了一个 EventListener“点击”。
其次,在 colourHover 函数中,根据按钮的 ID 调用 mouseover EventListener。
第三,EventListener-mouseover 在各自的函数 ( grayColour(event)
, yellowColour(event)
) 中定义。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body id="start">
<div class="container" id="grid">
</div>
<div><button type="button" class="button" id="gray">Gray Colour</button></div>
<div><button type="button" class="button" id="yellow">Yellow Colour</button></div>
<div><button type="button" id="button">Resize your grid manually.</button></div>
<script>
"use strict";
let container = document.getElementById("grid");
let n;
// creating a grid with number-input from user.
let makeGrid = function makeGrid(input) {
let c;
for (c = 0; c < (input * input); c++) {
let cell = document.createElement("div");
container.appendChild(cell).className = "squares";
};
container.style.gridTemplateColumns = `repeat(${input}, auto)`;
container.style.gridTemplateRows = `repeat(${input}, auto)`;
};
// function gets exectuted, only if a number and below 101
let numberCheck = function numberCheck() {
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
};
while ((n % n) !== 0) {
alert("Please enter a number.");
n = prompt("Choose again.");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
};
while ((n % n) === 0 && n > 100) {
alert("The number is too high.");
n = prompt("Choose again.");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
else if ((n % n) !== 0) {
alert("Please enter a number");
n = prompt("Choose again");
if ((n % n) === 0 && n <= 100) {
makeGrid(n);
}
}
};
};
// default grid on first pageload
makeGrid(16);
// this function sets the hovered items colour to black on default / first pageload
let blackColor = function blackColor(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "black";
};
};
// addEventListener for blackColor function
let hoverItems = document.querySelectorAll(".container");
hoverItems.forEach(element => { element.addEventListener("mouseover", blackColor)
});
// function to manual selecting a grid-size. Beforehand, old grid gets deleted
let removeElements = function removeElements(event) {
let elements = document.getElementsByClassName("squares");
while (elements.length > 0) {
elements[0].parentNode.removeChild(elements[0]);
};
n = prompt("Choose the size of your grid");
numberCheck(n);
};
// button for selecting a grid-size manually
let button = document.querySelector("#button");
button.addEventListener("click", removeElements);
// this function sets the background-color of the cells on mouseover to gray
let grayColour = function grayColour(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "gray"
}
}
// this function sets the background-color of the cells on mouseover to yellow
let yellowColour = function yellowColour(event) {
let colour = event.target;
if (colour.className === "container") {
return;
}
else if (colour.className === "squares") {
colour.style.backgroundColor = "yellow";
}
}
let colourHover = function colourHover(event) {
let hover = document.querySelectorAll(".container");
switch (event.target.id) {
case "gray":
//hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
//});
//hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
//});
hover.forEach(element => { element.addEventListener("mouseover", grayColour)
});
break;
case "yellow":
//hover.forEach(element => { element.removeEventListener("mouseover", yellowColour)
//});
//hover.forEach(element => { element.removeEventListener("mouseover", grayColour)
//});
hover.forEach(element => { element.addEventListener("mouseover", yellowColour)
});
break;
};
};
let colourBtn = document.querySelectorAll(".button");
colourBtn.forEach(element => { element.addEventListener("click", colourHover)
});
</script>
</body>
</html>
我很欣赏任何正确方向的提示。现在真的卡住了。
解决方案
最简单的方法是使用 CSS 类来设置单元格的样式,并在按钮单击处理程序中更改表格主体的类。“小部件”的状态应该存储在 JS 变量中,这样可以避免每次单击按钮时不必要的 DOM 遍历。像这样的东西:
const buttons = document.querySelectorAll('button'),
table = document.querySelector('.hovered-colors');
// The state of the widget
let currentColor = 'black';
buttons.forEach(button => {
button.addEventListener('click', e => {
const newColor = e.target.getAttribute('data-color');
table.classList.remove(currentColor);
table.classList.add(newColor);
currentColor = newColor;
});
});
.black td:hover {
color: white;
background-color: black;
}
.gray td:hover {
color: black;
background-color: gray;
}
.yellow td:hover {
color: black;
background-color: yellow;
}
<table>
<tbody class="hovered-colors black">
<tr><td>R1C1</td><td>R1C2</td></tr>
<tr><td>R2C1</td><td>R2C2</td></tr>
<tr><td>R3C1</td><td>R3C2</td></tr>
</tbody>
</table>
<button data-color="gray">Gray</button>
<button data-color="yellow">Yellow</button>
推荐阅读
- flutter - 如何根据其他小部件在 Row 中调整小部件的大小?
- ruby-on-rails - 如何使用 Haml 从公共目录修改 Rails 错误页面
- wordpress - 页面加载时专注于搜索
- qgis - 如何在qgis中查看信封?
- python - 将 Pandas Dataframe 中的数据行输入到 csv 文件中的下一个空行
- java - 如何处理 MethodArgumentNotValidException
- python - 如何在 Python 中去掉前导零
- html - ng For 循环仅返回数组中的最后一个值
- ruby - 如何从另一个类方法调用一个类方法
- c# - 在自己的 ServiceCollection 中获取 IConfiguration