本文旨在解决使用 JavaScript 为多个箭头元素添加点击旋转效果时遇到的 "addEventListener is not a function" 错误。我们将详细介绍如何正确地为通过 `getElementsByClassName()` 获取的元素集合添加事件监听器,并提供两种解决方案:使用 `for` 循环和 `forEach()` 方法,并附带示例代码,帮助你轻松实现箭头旋转效果。
在使用 JavaScript 为页面上的多个元素添加事件监听器时,经常会使用 document.getElementsByClassName() 方法来获取这些元素。然而,直接对 getElementsByClassName() 返回的结果(一个类数组对象 HTMLCollection)调用 addEventListener 方法会导致 "addEventListener is not a function" 错误。这是因为 HTMLCollection 对象本身并不具备 addEventListener 方法,该方法只能直接应用于单个 DOM 元素。
要解决这个问题,我们需要遍历 HTMLCollection 对象,并为其中的每个元素单独添加事件监听器。以下介绍两种常用的方法:
for 循环是一种传统的遍历数组的方式,同样适用于 HTMLCollection 对象。
(function (document) {
const div = document.getElementsByClassName("container");
const divLen = div.length;
let open = false;
for (let i = 0; i < divLen; ++i) {
div[i].addEventListener("click", function () {
const icon = this.getElementsByClassName("arrow")[0]; // 获取当前点击的 container 中的 arrow
if (open) {
icon.className = "fa fa-arrow-down";
} else {
icon.className = "fa fa-arrow-down rotate";
}
open = !open;
});
}
})(document);代码解释:
元素。注意: 在事件处理函数中使用 this 关键字非常重要,它可以确保我们获取到的是当前被点击的元素,而不是全局的 window 对象。
forEach() 方法是 ES6 引入的一种更简洁的数组遍历方式。虽然 HTMLCollection 对象本身没有 forEach() 方法,但我们可以使用 Array.prototype.forEach.call() 将其转换为数组,然后再使用 forEach() 方法。
(function (document) {
const div = document.getElementsByClassName("container");
let open = false;
Array.prototype.forEach.call(div, function (elem) {
elem.addEventListener("click", function () {
const icon = elem.getElementsByClassName("arrow")[0];
if (open) {
icon.className = "fa fa-arrow-down";
} else {
icon.className = "fa fa-arrow-down rotate";
}
open = !open;
});
});
})(document);代码解释:
注意: 使用 Array.prototype.forEach.call() 可以将类数组对象转换为真正的数组,从而可以使用数组的各种方法,例如 forEach()。
以下是包含 HTML、CSS 和 JavaScript 的完整示例代码:
HTML:
CSS:
.fa-arrow-down {
transform: rotate(0deg);
transition: transform 1s linear;
}
.fa-arrow-down.rotate {
transform: rotate(180deg);
transition: transform 1s linear;
}JavaScript (使用 for 循环):
(function (document) {
const div = document.getElementsByClassName("container");
const divLen = div.length;
let open = false;
for (let i = 0; i < divLen; ++i) {
div[i].addEventListener("click", function () {
const icon = this.getElementsByClassName("arrow")[0];
if (open) {
icon.className = "fa fa-arrow-down";
} else {
icon.className = "fa fa-arrow-down rotate";
}
open = !open;
});
}
})(document);JavaScript (使用 forEach 方法):
(function (document) {
const div = document.getElementsByClassName("container");
let open = false;
Array.prototype.forEach.call(div, function (elem) {
elem.addEventListener("click", function () {
const icon = elem.getElementsByClassName("arrow")[0];
if (open) {
icon.className = "fa fa-arrow-down";
} else {
icon.className = "fa fa-arrow-down rotate";
}
open = !open;
});
});
})(document);总结:
通过本文的介绍,你现在应该能够正确地为通过 getElementsByClassName() 获取的元素集合添加事件监听器,并成功实现箭头旋转效果。无论你选择使用 for 循环还是 forEach() 方法,关键在于理解 getElementsByClassName() 返回的是一个 HTMLCollection 对象,需要遍历该对象才能为每个元素单独添加事件监听器。希望本文对你有所帮助!