如何识别在for循环中添加eventListener时单击的元素



我正在尝试制作一个FAQ列表,一次只扩展一个问题,我的方法是在for循环中向所有问题元素添加事件侦听器,问题是我无法确定点击了哪个元素,我知道我可以单独添加事件侦听程序,但我想了解这种方法:

js代码:

var query = document.getElementsByClassName("query");
for (var i = 0 ; i < query.length; i++) {

query[i].addEventListener('click' , function(){

for (var j = 0 ; j < query.length; j++) {
query[j].classList.remove("active");
console.log("acitve state removed");
}
query[i].classList.add("active");// undefined since "query array is only 0-1 and i = 2 at this stage "
console.log("activated");
}) ; 
}

html代码:

<div class="query">
<p class="question">How many team members can I invite?</p>
<img src="/images/icon-arrow-down.svg" alt="icon-arrow-down">
<p class="answer">You can invite up to 2 additional users on the Free plan. There is no limit on 
team members for the Premium plan.</p>
</div>
<div class="query">
<p class="question">What is the maximum file upload size?</p>
<img src="/images/icon-arrow-down.svg" alt="icon-arrow-down">
<p class="answer">  No more than 2GB. All files in your account must fit your allotted storage space.
</p>
</div>

控制台错误:

未捕获类型错误:无法读取未定义的属性"classList">

query[i]替换为this。这总是指向为其分配事件处理程序的元素。

如果要使用querySelectorAll获取节点列表,则可以像遍历数组一样遍历该节点列表,并以稍微不同的方式分配事件侦听器,该方式不依赖于如上所述的索引。

const clickhandler = function(e) {
let col = document.querySelectorAll('.query');
col.forEach(n => n.classList.remove('active'))
this.classList.add('active')
};
document.querySelectorAll('div.query').forEach(n => n.addEventListener('click', clickhandler))
.query {
border: 1px solid red;
margin: 1rem;
padding: 1rem;
}
.active {
background: pink
}
<div class="query">
<p class="question">How many team members can I invite?</p>
<img src="/images/icon-arrow-down.svg" alt="icon-arrow-down">
<p class="answer">You can invite up to 2 additional users on the Free plan. There is no limit on team members for the Premium plan.
</p>
</div>
<div class="query">
<p class="question">What is the maximum file upload size?</p>
<img src="/images/icon-arrow-down.svg" alt="icon-arrow-down">
<p class="answer">
No more than 2GB. All files in your account must fit your allotted storage space.
</p>
</div>

我在使用let–时遇到了一些gull包问题

就我个人而言,我会在这里用gullow来解决这个问题。

但是,如果由于某种原因不能使用let,那么可以通过创建一个函数范围的包装器来确定var的旧方法。

例如。

//Wrong
for (var i = 0; i < 10; i += 1) {
setTimeout(function () { console.log(i) }, 1);
}
//Correct
for (var i = 0; i < 10; i += 1) {
setTimeout(
function (i) {
return function () { console.log(i) };
}(i)
,1);
}

当在循环中添加事件侦听器时,最好在匿名函数或外部函数中确定其范围:

var query = document.getElementsByClassName("query");
for (var i = 0; i < query.length; i++) {
(function(qi, qa) {
qi.addEventListener('click', function() {
for (var j = 0; j < qa.length; j++) {
qa[j].classList.remove("active");
console.log("active state removed");
}
qi.classList.add("active");
console.log("activated");
})
})(query[i], query);
}

工作:https://jsfiddle.net/nqkshf3w/

最新更新