如何为数组进行事件委托?(或 NodeList)
How to do Event delegation for an Array?(or NodeList)
我这辈子第一次尝试使用 Event delegation/switch 语句,但遇到了 for 循环的问题。当它是 'array[i]' 时,这不是问题。但是现在我要删除 for 循环以使用事件委托并将其放在函数内部,它一直给我错误,而且我不知道什么参数可以替换(并使代码再次运行)数组 [i ] 在新功能中。任何帮助或解释将不胜感激。
//original code
const numbers = document.querySelectorAll(".number");
for (let i = 0; i < numbers.length; i++) {
numbers[i].addEventListener("click", function () {
if (display.value.length < 13) {
return;
}
if (display.value == "0" && numbers[i] != dot) {
display.value = numbers[i].innerText;
calculation = display.value;
} else {
if (numbers[i] == dot && display.value.includes(".")) {
return;
} else if (numbers[i] == dot && display.value == "") {
return;
} else {
display.value += numbers[i].innerText;
calculation = display.value;
}
}
buttonEffect(numbers[i], "number-active");
});
}
// New code
const numbers = document.querySelectorAll(".number");
function numberClick(number) {
if (display.value.length > 13) {
return;
}
if (display.value == "0" && this != dot) {
display.value = number.innerText;
calculation = display.value;
} else {
if (numbers == dot && display.value.includes(".")) {
return;
} else if (number == dot && display.value == "") {
return;
} else {
display.value += number.innerText;
calculation = display.value;
}
}
operatorOnOff = false;
buttonEffect(number, "number-active");
}
document.querySelector(".wrapper").addEventListener("click", (e) => {
switch (e.target.dataset.key) {
case "number":
numberClick();
break;
}
});
您将作为点击目标的元素传递到 numberClick
并在您之前使用的地方使用它 numbers[i]
。看起来你已经在做第二部分了,你甚至已经为它声明了一个参数,你只需要传递元素:
numberClick(e.target);
请注意,如果您的 .number
元素具有子元素,则 target
可能是这些子元素之一,而不是 .number
。要处理这个问题,您可以使用 DOM 相对较新的 closest
方法,可能与 contains
结合使用以确保它与 .wrapper
周围的东西不匹配:
document.querySelector(".wrapper").addEventListener("click", (e) => {
const number = e.target.closest(".number");
if (number && this.contains(number) && number.dataset.key) {
numberClick(number);
}
});
如果你需要支持过时的浏览器,或者你自己做循环,你可以使用 polyfills:
document.querySelector(".wrapper").addEventListener("click", (e) => {
let number = e.target;
while (number && !number.matches(".number")) {
if (this === number) {
return; // Reached the wrapper without finding it
}
number = number.parentElement;
}
if (number && number.dataset.key) {
numberClick(number);
}
});
我这辈子第一次尝试使用 Event delegation/switch 语句,但遇到了 for 循环的问题。当它是 'array[i]' 时,这不是问题。但是现在我要删除 for 循环以使用事件委托并将其放在函数内部,它一直给我错误,而且我不知道什么参数可以替换(并使代码再次运行)数组 [i ] 在新功能中。任何帮助或解释将不胜感激。
//original code
const numbers = document.querySelectorAll(".number");
for (let i = 0; i < numbers.length; i++) {
numbers[i].addEventListener("click", function () {
if (display.value.length < 13) {
return;
}
if (display.value == "0" && numbers[i] != dot) {
display.value = numbers[i].innerText;
calculation = display.value;
} else {
if (numbers[i] == dot && display.value.includes(".")) {
return;
} else if (numbers[i] == dot && display.value == "") {
return;
} else {
display.value += numbers[i].innerText;
calculation = display.value;
}
}
buttonEffect(numbers[i], "number-active");
});
}
// New code
const numbers = document.querySelectorAll(".number");
function numberClick(number) {
if (display.value.length > 13) {
return;
}
if (display.value == "0" && this != dot) {
display.value = number.innerText;
calculation = display.value;
} else {
if (numbers == dot && display.value.includes(".")) {
return;
} else if (number == dot && display.value == "") {
return;
} else {
display.value += number.innerText;
calculation = display.value;
}
}
operatorOnOff = false;
buttonEffect(number, "number-active");
}
document.querySelector(".wrapper").addEventListener("click", (e) => {
switch (e.target.dataset.key) {
case "number":
numberClick();
break;
}
});
您将作为点击目标的元素传递到 numberClick
并在您之前使用的地方使用它 numbers[i]
。看起来你已经在做第二部分了,你甚至已经为它声明了一个参数,你只需要传递元素:
numberClick(e.target);
请注意,如果您的 .number
元素具有子元素,则 target
可能是这些子元素之一,而不是 .number
。要处理这个问题,您可以使用 DOM 相对较新的 closest
方法,可能与 contains
结合使用以确保它与 .wrapper
周围的东西不匹配:
document.querySelector(".wrapper").addEventListener("click", (e) => {
const number = e.target.closest(".number");
if (number && this.contains(number) && number.dataset.key) {
numberClick(number);
}
});
如果你需要支持过时的浏览器,或者你自己做循环,你可以使用 polyfills:
document.querySelector(".wrapper").addEventListener("click", (e) => {
let number = e.target;
while (number && !number.matches(".number")) {
if (this === number) {
return; // Reached the wrapper without finding it
}
number = number.parentElement;
}
if (number && number.dataset.key) {
numberClick(number);
}
});