繁体   English   中英

单击另一个循环时将事件侦听器添加到元素

[英]Adding event Listener to elements on click of another in loop

我的打字稿项目有很烦人的问题。 没什么可看的,但出于某种原因,一旦我单击这 3 个菜单中的任何一个元素,onclick 执行的次数与特定菜单中的元素数量一样多,而不是每次单击一次。

我已经尝试了一段时间,因此在评论或不同的添加侦听器中,功能略有不同。

如何使这些 EventListeners 只执行一次在菜单中选择一个选项

onst menu1 = document.getElementById("menu1") as HTMLDivElement;
const menu2 = document.getElementById("menu2") as HTMLDivElement;
const menu3 = document.getElementById("menu3") as HTMLDivElement;



menu1.addEventListener("click",  function () {

  let elements = menu1.querySelectorAll("input");
  for(let i=0; i< elements.length; i++) {
      elements[i].addEventListener("click", function () {
        if (elements[i].checked) {
          let val = elements[i].value;
          dataSet.setEffect(elements[i].value);
          console.log(dataSet);
        }
      });
    }
});


menu2.addEventListener("click", function(){

  const elements2 = menu1.querySelectorAll("label");
  // for (let element of elements2) {
  //   element.addEventListener("click", function () {
  //       dataSet.setEffect(element.value);
  //       console.log(dataSet);
  //   });
  // }
  elements2.forEach( function (ele,index) {
      // ele.addEventListener("click", function () {
      //         dataSet.setEffect(ele.innerText);
      //         console.log(dataSet);
      // });
  ele.onclick = function () {
    dataSet.setEffect(ele.innerText);
    console.log(dataSet,ele);
  }
  })

});


menu3.addEventListener("click", ()=>{
  let elements3 = menu3.children;
  for(let i=0; i< elements3.length; i++)
  {
    elements3[i].addEventListener("click", ()=>{
      dataSet.setBGC(elements3[i].id);
      console.log(dataSet);
    });
  }
});

单个菜单的 html

 <div class="container">
        <div class="header-text">
            <h2>Effect</h2>
        </div>
        <div class="select" id="menu1" tabindex="1">
            <input class="options-select"  value="solidColor" name="selectors1" type="radio" id="opt1" checked>
                <label for="opt1" class="option">Solid Color</label>
            <input class="options-select" value="EQCenter" name="selectors1" type="radio" id="opt2">
                <label for="opt2" class="option">EQ Center</label>
            <input class="options-select" value="Strobe" name="selectors1" type="radio" id="opt3">
                <label for="opt3" class="option">Strobe</label>
            <input class="options-select" value="Sparkel" name="selectors1" type="radio" id="opt4">
                <label for="opt4" class="option">Sparkel</label>
            <input class="options-select" value="swicth" name="selectors1" type="radio" id="opt5">
                <label for="opt5" class="option">Switch</label>
        </div>
        
    </div>

问题是事件传播之一(也称为“冒泡”,如链接的 MDN 文章中所述)。 每次单击input的一个时,它也会触发每个父元素上的事件。 由于这包括菜单本身,您的事件处理程序再次运行 - 为每个项目添加更多事件侦听器。

解决这个问题的最简单的代码更改就是使用事件对象的内置stopPropagation方法来防止这种情况:

  elements[i].addEventListener("click", function (event) {
    event.stopPropagation();
    if (elements[i].checked) {
      let val = elements[i].value;
      dataSet.setEffect(elements[i].value);
      console.log(dataSet);
    }
  });

但是,虽然这应该可以解决问题,但我强烈建议您考虑实现目标的不同方法。 在另一个事件侦听器中添加一个事件侦听器基本上是一种反模式 - 它很容易导致像你在这里遇到的问题,我正在努力思考任何需要或有用的情况。 由于您的输入就在 HTML 源代码中,而不是使用 Javascript 动态添加,因此我看不出有任何理由不能在加载页面时直接将事件侦听器添加到每个输入。 这将导致更清晰和更简单的代码。

你写了:

每次单击menu1 ,将一个新的 onClick 侦听器附加到他的每个孩子。

menu1.addEventListener("click",  function () {
  let elements = menu1.querySelectorAll("input");
  for(let i=0; i< elements.length; i++) {
      elements[i].addEventListener("click", function () {
        if (elements[i].checked) {
          let val = elements[i].value;
          dataSet.setEffect(elements[i].value);
          console.log(dataSet);
        }
      });
    }
});

只需替换为

let elements = menu1.querySelectorAll("input");
for(let i=0; i< elements.length; i++) {
  let elem = elements[i]; //To avoid the common closure problem
  elem.addEventListener("click", function () {
    if (elem.checked) {
      let val = elem.value;
      dataSet.setEffect(elem.value);
      console.log(dataSet);
    }
   });
}

难以将唯一的事件侦听器添加到已创建的<div>通过 for 循环的元素</div><div id="text_translate"><p>我正在做一个项目来学习一些 JavaScript,目标是在单页 web 应用程序中动态提供电子邮件。 应用程序的HTML已经使用createElement JS方法创建。 到目前为止,我已经成功地显示了包含所有电子邮件的“收件箱”页面,如下图所示:</p><p> <a href="https://i.stack.imgur.com/V8cZq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/V8cZq.png" alt=""></a></p><p> 我目前正在尝试通过使用 addEventListener 使这些单独的电子邮件中的每一个都可以点击。 我遇到的问题是,每当我单击任何一封电子邮件时,都会呈现收件箱中的第一个 email(id:1,主题:测试电子邮件),并且无法查看任何其他电子邮件。</p><p> <a href="https://i.stack.imgur.com/BBjQj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BBjQj.png" alt=""></a></p><p> 我可以看到相同的 email.id 被应用到所有创建的 div 的事件侦听器,尽管所有 div 都被正确创建,并包含来自相应电子邮件的所有信息。</p><p> 这是加载邮箱 JS,它呈现收件箱中的所有电子邮件:</p><pre> function load_mailbox(mailbox) { // Show the mailbox and hide other views document.querySelector('#emails-view').style.display = 'block'; document.querySelector('#compose-view').style.display = 'none'; document.querySelector('#single-view').style.display = 'none'; // Show the mailbox name document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`; // GET request fetch(`/emails/${mailbox}`).then(response => response.json()).then(emails => { // Print emails to console console.log(emails); // Iterate through each email for(var i = 0; i < emails.length; i++) { var email = emails[i]; // Create div and append email content to HTML var emaildiv = document.createElement('div'); emaildiv.style.borderStyle = 'solid'; emaildiv.style.borderColor = 'black'; emaildiv.style.borderWidth = '0.1rem'; emaildiv.style.borderRadius = '0'; emaildiv.style.marginBottom = '0.2rem'; emaildiv.style.padding = '0.3rem'; emaildiv.innerHTML = `<b>${email.sender}</b> --- ${email.subject}<br>${email.timestamp}`; // If individual email selected then view email emaildiv.addEventListener('click', () => view_email(email)); // Populate div HTML with emails document.querySelector('#emails-view').append(emaildiv); console.log(email.read); // Colour backgrounds based on whether emails have been read if (email.read == true) { emaildiv.style.backgroundColor = 'lightgrey'; } console.log(email); } });}</pre><p> 这是视图 email JS,它应该渲染个人 email 的 HTML:</p><pre> // View email function view_email(email) { console.log(email.id); // Show the mailbox and hide other views document.querySelector('#emails-view').style.display = 'none'; document.querySelector('#compose-view').style.display = 'none'; document.querySelector('#single-view').style.display = 'block'; // GET request fetch(`/emails/${email["id"]}`).then(response => response.json()).then(email => { // Create div, set class, and append email content to HTML var reademail = document.createElement('div'); reademail.innerHTML = ''; reademail.style.borderStyle = 'solid'; reademail.style.borderColor = 'black'; reademail.style.borderWidth = '0.1rem'; reademail.style.borderRadius = '0'; reademail.style.marginBottom = '0.2rem'; reademail.style.padding = '0.3rem'; reademail.innerHTML = ` <b>From:</b> ${email.sender}<br> <b>To:</b> ${email.recipients}<br> <b>Subject:</b> ${email.subject}<br> <b>Timestamp:</b> ${email.timestamp}<br> <button class="btn btn-sm btn-outline-primary" id="Reply">Reply</button> <hr> ${email.body}`; // Populate div HTML with emails document.querySelector('#single-view').append(reademail); // Mark unread emails as read if (email.read === 'false') { fetch(`/emails/${email}`, { method: 'PUT', body: JSON.stringify({ read: true }) }) } }); }</pre><p> 这是存储在 email GET 响应中的示例(虚拟数据):</p><pre> { "id": 1, "sender": "user@example.com", "recipients": ["user@example.com"], "subject": "Hello,": "body", "Hello, world:", "timestamp": "Oct 24 2020, 12:00 AM", "read": false, "archived": false }</pre><p> 我已经尝试将其他每封电子邮件的 ID 硬编码到视图 email JS 中,并且可以看到该功能按要求工作(显示电子邮件)。</p><p> 因此,我知道问题与上面的加载邮箱 JS 有关,并且可能与事件侦听器如何在 for 循环中应用有关。 如果有人可以阐明如何将唯一的事件侦听器应用于每个单独的 div,将不胜感激。</p><p> 谢谢!</p></div>

[英]Difficulty adding unique event listener to created <div> elements via a for loop

暂无
暂无

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

相关问题 向具有相同类的元素添加单击事件侦听器 使用“ for”循环添加“ click”事件监听器 点击循环事件监听器 向所有元素添加单击事件侦听器-Firefox附加组件 难以将唯一的事件侦听器添加到已创建的<div>通过 for 循环的元素</div><div id="text_translate"><p>我正在做一个项目来学习一些 JavaScript,目标是在单页 web 应用程序中动态提供电子邮件。 应用程序的HTML已经使用createElement JS方法创建。 到目前为止,我已经成功地显示了包含所有电子邮件的“收件箱”页面,如下图所示:</p><p> <a href="https://i.stack.imgur.com/V8cZq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/V8cZq.png" alt=""></a></p><p> 我目前正在尝试通过使用 addEventListener 使这些单独的电子邮件中的每一个都可以点击。 我遇到的问题是,每当我单击任何一封电子邮件时,都会呈现收件箱中的第一个 email(id:1,主题:测试电子邮件),并且无法查看任何其他电子邮件。</p><p> <a href="https://i.stack.imgur.com/BBjQj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BBjQj.png" alt=""></a></p><p> 我可以看到相同的 email.id 被应用到所有创建的 div 的事件侦听器,尽管所有 div 都被正确创建,并包含来自相应电子邮件的所有信息。</p><p> 这是加载邮箱 JS,它呈现收件箱中的所有电子邮件:</p><pre> function load_mailbox(mailbox) { // Show the mailbox and hide other views document.querySelector('#emails-view').style.display = 'block'; document.querySelector('#compose-view').style.display = 'none'; document.querySelector('#single-view').style.display = 'none'; // Show the mailbox name document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`; // GET request fetch(`/emails/${mailbox}`).then(response => response.json()).then(emails => { // Print emails to console console.log(emails); // Iterate through each email for(var i = 0; i < emails.length; i++) { var email = emails[i]; // Create div and append email content to HTML var emaildiv = document.createElement('div'); emaildiv.style.borderStyle = 'solid'; emaildiv.style.borderColor = 'black'; emaildiv.style.borderWidth = '0.1rem'; emaildiv.style.borderRadius = '0'; emaildiv.style.marginBottom = '0.2rem'; emaildiv.style.padding = '0.3rem'; emaildiv.innerHTML = `<b>${email.sender}</b> --- ${email.subject}<br>${email.timestamp}`; // If individual email selected then view email emaildiv.addEventListener('click', () => view_email(email)); // Populate div HTML with emails document.querySelector('#emails-view').append(emaildiv); console.log(email.read); // Colour backgrounds based on whether emails have been read if (email.read == true) { emaildiv.style.backgroundColor = 'lightgrey'; } console.log(email); } });}</pre><p> 这是视图 email JS,它应该渲染个人 email 的 HTML:</p><pre> // View email function view_email(email) { console.log(email.id); // Show the mailbox and hide other views document.querySelector('#emails-view').style.display = 'none'; document.querySelector('#compose-view').style.display = 'none'; document.querySelector('#single-view').style.display = 'block'; // GET request fetch(`/emails/${email["id"]}`).then(response => response.json()).then(email => { // Create div, set class, and append email content to HTML var reademail = document.createElement('div'); reademail.innerHTML = ''; reademail.style.borderStyle = 'solid'; reademail.style.borderColor = 'black'; reademail.style.borderWidth = '0.1rem'; reademail.style.borderRadius = '0'; reademail.style.marginBottom = '0.2rem'; reademail.style.padding = '0.3rem'; reademail.innerHTML = ` <b>From:</b> ${email.sender}<br> <b>To:</b> ${email.recipients}<br> <b>Subject:</b> ${email.subject}<br> <b>Timestamp:</b> ${email.timestamp}<br> <button class="btn btn-sm btn-outline-primary" id="Reply">Reply</button> <hr> ${email.body}`; // Populate div HTML with emails document.querySelector('#single-view').append(reademail); // Mark unread emails as read if (email.read === 'false') { fetch(`/emails/${email}`, { method: 'PUT', body: JSON.stringify({ read: true }) }) } }); }</pre><p> 这是存储在 email GET 响应中的示例(虚拟数据):</p><pre> { "id": 1, "sender": "user@example.com", "recipients": ["user@example.com"], "subject": "Hello,": "body", "Hello, world:", "timestamp": "Oct 24 2020, 12:00 AM", "read": false, "archived": false }</pre><p> 我已经尝试将其他每封电子邮件的 ID 硬编码到视图 email JS 中,并且可以看到该功能按要求工作(显示电子邮件)。</p><p> 因此,我知道问题与上面的加载邮箱 JS 有关,并且可能与事件侦听器如何在 for 循环中应用有关。 如果有人可以阐明如何将唯一的事件侦听器应用于每个单独的 div,将不胜感激。</p><p> 谢谢!</p></div> 使用for循环并传递不同的参数将事件侦听器添加到多个元素 在具有循环和jQuery的同一类的所有元素上添加Click事件 如何将点击事件监听器添加到每个元素? 附加到一键事件侦听器的多个元素 在脚本中添加点击事件监听器不起作用
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM