javascript - 如何将EventListener 添加到此for 循环中的每个innerHTML += ?

标签 javascript html loops events sass

我正在尝试在某些重复的 innerHTML 上添加事件监听器。即对于由innerHTML 添加的每批HTML,我还需要在其上添加一个点击事件。

为了使事情复杂化,我还从另一个以 data 名称导入的 JS 文件导入数据集。正如您在代码中看到的,我需要事件监听器内的数据特定于innerHTML 的for 循环迭代,以便当我触发事件监听器时我可以看到正确的相应数据。

这是我的尝试:

JS:

import data from './data.js';
import img from './images.js';

export const lists = () => {
  const main = document.getElementById('main');

  main.innerHTML = `
  <div class="main-container">
    <div class="flex-between row border-bottom">
      <div class="flex new-list">
        <img class="create-img img-radius" src="${img.symbols[0]}" alt="Delete Bin">
        <h3>New List</h3>  
      </div>
      <div class="flex-between sections">
        <h3 class="text-width flex-c">Items:</h3>
        <h3 class="text-width flex-c">Reminders:</h3>
        <h3 class="text-width flex-end">Created:</h3>
      </div>
    </div>
    <div id="lists"></div>
  </div>
  `;

  const lists = document.getElementById('lists');

  for (let i = 0; i < data.lists.length; i++) {
    let obj = eval(data.lists[i]);
    let totalReminders = getTotalReminders(obj);

    lists.innerHTML += `
    <div class="flex-between row list">
      <h4>${obj.name}</h4>
      <div class="flex-between sections">
        <h4 class="number-width flex-c">${obj.items.length}</h4>
        <h4 class="number-width flex-c">${totalReminders}</h4>
        <div class="text-width flex-end">
          <h4 class="date">${obj.created}</h4>
          <img class="img-radius" src="${img.symbols[3]}" alt="Delete Bin">
        </div>
      </div>
    </div>
    `;

    const list = document.querySelector('.list');

    list.addEventListener('click', () => { // click event
      listNav.listNav(obj.name);
      listSidebarL.listSidebarL();
      listSidebarR.listSidebarR();
      listMain.listMain(obj.items);
    });
  };
};

const getTotalReminders = passed => { // find total reminders
  let total = 0;

  for (let i = 0; i < passed.items.length; i++) {
    total += passed.items[i].reminders;
  };

  return total;
};

目前,只有 innerHTML += 的第一次迭代附加了事件监听器,当我单击它时,我会看到应与最后一次迭代相对应的数据。

我在这里做错了什么?

最佳答案

您需要移动设置事件处理程序的代码,以便它位于 for 循环之外并在该循环完成后运行。然后,您需要 .querySelectorAll() 来返回所有匹配元素,而不是仅返回第一个匹配元素的 .querySelector()。之后,您将循环遍历所有这些元素并设置处理程序。

您还需要更改 obj 变量的声明方式,使其位于 for 循环之外的范围内。通过在循环之前声明它,但在循环内分配它来做到这一点:

let obj = null; // Now, obj is scoped so it can be accessed outside of the loop
for (let i = 0; i < data.lists.length; i++) {
  obj = eval(data.lists[i]);

并且,将以下内容放在 for 循环结束之后:

// Get all the .list elements into an Array
const list = Array.prototype.slice.call(document.querySelectorAll('.list'));

// Loop over the array and assign an event handler to each array item:
list.forEach(function(item){
  item.addEventListener('click', () => { 
    listNav.listNav(obj.name);
    listSidebarL.listSidebarL();
    listSidebarR.listSidebarR();
    listMain.listMain(obj.items);
  });
});

话虽如此,你的做法确实不太好。除了使用 eval() 之外,几乎总是有另一种选择,而使用 .innerHTML 由于其安全性和性能影响,通常需要避免。循环使用它几乎总是一个坏主意。您确实应该使用 DOM API 来创建新元素、配置它们并将它们注入(inject)到 DOM 中。如果您必须使用 .innerHTML,则在循环中构建一个字符串,并在循环之后通过 .innerHTML 将字符串注入(inject)到 DOM 中,只需一次。

关于javascript - 如何将EventListener 添加到此for 循环中的每个innerHTML += ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55602951/

相关文章:

html - Z-index 问题 - 如何将子元素带到父元素的下面?

javascript - 正则表达式限制字母表

html - CSS :before pseudoelement: vertically centered

java - 在 for 循环中为每次迭代声明一个新变量

javascript - 仅使用最后一个数组项动态生成的内容

javascript - 尽管使用 .bind(this) ,但 this 指的是全局对象

javascript - 动态添加html内容时出现意外的 token 非法错误

JavaScript - 页面加载完成后按空格键

php - 从Wordpress查询中排除帖子ID

jquery - 使用 jQuery 遍历 HTML 复选框