我有一个网站,看起来像下面。当文本被点击时,被点击的文本将获得一个名为large的类,并且文本大小将更改为25pt。要查看我如何分配事件和类大,请查看js代码。我遇到的问题是当文本"我喜欢游泳"时点击大类被添加到文本"我喜欢篮球"。为什么会发生这种情况?有人能帮我解决这个问题吗?
const arraySportsText = Array.from(document.getElementsByClassName('sportsText'));
for (index in arraySportsText) {
arraySportsText[index].addEventListener("click", () => arraySportsText[index].classList.add('large'))
}
body {
font-size: 15pt;
}
.large {
font-size: 25pt;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="styles/style.css">
</head>
<body>
<h1>Sports</h1>
<p class="sportsText">I like swimming</p>
<p class="sportsText">I like basketball</p>
<script src="scripts/hobby.js"></script>
</body>
</html>
你的循环变量没有显式声明,所以它得到一个隐式的var
声明作为一个全局变量。
在事件处理程序中使用循环变量创建了围绕index
的闭包,因此当这些处理程序运行(稍后)时,它们访问该循环变量的最后一个值,因此只有最后一个元素受到影响。
使用let
声明你的循环变量块作用域来解决这个问题。
- 另外,不要使用
.getElementsByClassName()
和代替使用.querySelectorAll()
. .getElementsByClassName()
和.querySelectorAll()
返回类数组的集合,所以两者都不是如果要使用计数循环,则需要Array.from()
迭代。- 并且,
for/in
循环不应该在数组上使用,因为它们枚举数组的所有属性,而不仅仅是索引。for/in
应该只在对象上使用 最后,
.querySelectorAll()
返回的集合可以是循环使用Array.prototype.forEach()
方法,删除需要计数循环。所以,修改后的代码应该是:
// Looping over the collection returned from .querySelectorAll()
// eliminates the need for a counting loop, which also removes
// the need to use that index in the event handler, which in turn,
// eliminates the closure problem you had in the first place.
document.querySelectorAll('.sportsText').forEach(function(element){
element.addEventListener("click", () => element.classList.add('large'))
});
body { font-size: 15pt; }
.large { font-size: 25pt; }
<h1>Sports</h1>
<p class="sportsText">I like swimming</p>
<p class="sportsText">I like basketball</p>