我正在尝试制作一个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/