简体   繁体   English

使用 for 循环将事件监听器添加到按钮数组

[英]addEventListener to an array of buttons using a for loop

I am trying to made a series of buttons (in the div included in the html) give an alert when clicked.我试图让一系列按钮(在 html 中包含的 div 中)在点击时发出警报。 For that I am using addEventListener.为此,我正在使用 addEventListener。 If I just make a list (as showed belowed commented) the result is fine.如果我只是列出一个列表(如下面的评论所示),结果很好。 I try to make the code DRY by using a for loop but it returns me only that "clicked 8" no matter what I press.我尝试使用 for 循环使代码变干,但无论我按什么,它都只返回“点击 8”。 As far as I understand the flow should start by testing i=0 and continue with the others the same way as with the entire list.据我所知,流程应该从测试 i=0 开始,然后以与整个列表相同的方式继续其他流程。 So if I press the button[0] I should get "clicked 1" and that's all because the other conditions are false.所以如果我按下按钮[0],我应该得到“点击1”,这都是因为其他条件是假的。 Thanks in advance.提前致谢。

 // document.querySelectorAll("button")[0].addEventListener("click", function(){alert("clicked 1")}); // document.querySelectorAll("button")[1].addEventListener("click", function(){alert("clicked 2")}); // document.querySelectorAll("button")[2].addEventListener("click", function(){alert("clicked 3")}); // document.querySelectorAll("button")[3].addEventListener("click", function(){alert("clicked 4")}); // document.querySelectorAll("button")[4].addEventListener("click", function(){alert("clicked 5")}); // document.querySelectorAll("button")[5].addEventListener("click", function(){alert("clicked 6")}); // document.querySelectorAll("button")[6].addEventListener("click", function(){alert("clicked 7")}); for(i=0; i<=6; i++) { document.querySelectorAll("button")[i].addEventListener("click", function(){alert("clicked " + (i+1))}); }
 <div class="set"> <button class="w drum">w</button> <button class="a drum">a</button> <button class="s drum">s</button> <button class="d drum">d</button> <button class="j drum">j</button> <button class="k drum">k</button> <button class="l drum">l</button> </div>

Your issue comes from the behavior of using var keyword to define variable.您的问题来自使用var关键字定义变量的行为。

In ES6 there were introduced let and const keywords.在 ES6 中引入了letconst关键字。 If you use them you will stop facing issues of var hoisting and scope.如果您使用它们,您将不再面临var提升和范围的问题。

So, you can add a let keyword to your i declaration like this:因此,您可以像这样在i声明中添加一个let关键字:

for (let i=0; i<=6; i++) {
  //the rest of the code
}

You can read more in this question .您可以在这个问题中阅读更多内容。

Short summary of the linked question in your issue问题中链接问题的简短摘要

When you write i = 0 you are defining the i property in the window object.当您写入i = 0您是在定义window对象中的i属性。 Then in loop you are incrementing this value.然后在循环中增加这个值。 When using i in passed function, javascript is getting the value from window object.在传递的函数中使用i时,javascript 正在从window对象获取值。

On the other hand, let keyword defines the scope of variable to the scope of your loop, so passed function always contains copy of value, when the function was passed.另一方面, let关键字将变量的范围定义为循环的范围,因此传递的函数始终包含值的副本,当传递函数时。

It seems like the function keeps track of the value of I even after the loop.即使在循环之后,该函数似乎也会跟踪 I 的值。 Add another variable and bind it to the alert添加另一个变量并将其绑定到警报

 // document.querySelectorAll("button")[0].addEventListener("click", function(){alert("clicked 1")}); // document.querySelectorAll("button")[1].addEventListener("click", function(){alert("clicked 2")}); // document.querySelectorAll("button")[2].addEventListener("click", function(){alert("clicked 3")}); // document.querySelectorAll("button")[3].addEventListener("click", function(){alert("clicked 4")}); // document.querySelectorAll("button")[4].addEventListener("click", function(){alert("clicked 5")}); // document.querySelectorAll("button")[5].addEventListener("click", function(){alert("clicked 6")}); // document.querySelectorAll("button")[6].addEventListener("click", function(){alert("clicked 7")}); for(var i=0;i<7; i++) { let out = i+1 document.getElementsByTagName("button")[i].addEventListener("click", function(){alert("clicked " + (out))}); }
 <div class="set"> <button class="w drum">w</button> <button class="a drum">a</button> <button class="s drum">s</button> <button class="d drum">d</button> <button class="j drum">j</button> <button class="k drum">k</button> <button class="l drum">l</button> </div>

you can dry your code in this way:你可以用这种方式干燥你的代码:

document.querySelectorAll('button').forEach((el, i) => {
    el.addEventListener('click', () => alert(`clicked ${i+1}`))
} )

Instead of attaching listeners to all the buttons you might take advantage of event delegation which allows you to add one listener to the parent element ( .set in this case), and catch events from the buttons as they "bubble up" the DOM.您可以利用事件委托,而不是将侦听器附加到所有按钮,它允许您将一个侦听器添加到父元素(在本例中为.set ),并在按钮“冒泡”DOM 时从按钮中捕获事件。

In this example I'm logging the text content of the buttons when they are clicked.在这个例子中,我记录了按钮被点击时的文本内容。

 // Cache the parent element and add a listener const set = document.querySelector('.set'); set.addEventListener('click', handleClick, false); function handleClick(e) { // Extract the nodeName and textContent from // the clicked element const { nodeName, textContent } = e.target; // If it's a button, log the text if (nodeName === 'BUTTON') { console.log(textContent); } }
 <div class="set"> <button class="w drum">w</button> <button class="a drum">a</button> <button class="s drum">s</button> <button class="d drum">d</button> <button class="j drum">j</button> <button class="k drum">k</button> <button class="l drum">l</button> </div>

Additional documentation附加文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM