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

时间:2019-04-10 00:11:26

标签: javascript html loops events sass

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

为了使事情复杂化,我还要从以名称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 +=的第一次迭代仅附加了一个事件侦听器,当我单击它时,我看到的数据应该与最后一次迭代相对应。

我在这里做什么错了?

2 个答案:

答案 0 :(得分:2)

您需要移动设置事件处理程序的代码,以使其位于for循环之外,并在该循环结束后运行。然后,您需要#df=data sub=df.dropna()#drop na subup=sub.reindex(sub.index.repeat((sub.up).astype(int))) subup.index=subup.index-subup.groupby(level=0).cumcount(ascending=False)-1 subdown=sub.reindex(sub.index.repeat((sub.down).astype(int))) subdown.index=subdown.index+subdown.groupby(level=0).cumcount()+1 pd.concat([subup,subdown,sub])['fullwindow'].astype(str).str.get_dummies().sum(level=0).reindex(df.index,fill_value=0) Out[151]: 2.0 3.0 4.0 5.0 0 1 0 0 0 1 0 0 0 0 2 0 0 0 0 3 0 1 0 0 4 0 1 1 0 5 0 1 1 0 6 0 0 1 0 7 0 0 1 0 8 0 0 0 0 9 0 0 0 1 10 0 0 0 1 11 0 0 0 1 来返回所有匹配的元素,而不是仅返回第一个匹配元素的.querySelector()。之后,您将遍历所有这些元素并设置处理程序。

您还需要更改声明.querySelectorAll()变量的方式,使其位于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()。循环使用它几乎总是一个坏主意。您确实应该使用DOM API来创建新元素,对其进行配置并将它们注入DOM。如果必须使用.innerHTML,则在循环中构建一个字符串,然后在循环之后,通过.innerHTML将字符串一次注入DOM。

答案 1 :(得分:0)

一种选择是查看事件delegation/bubbling。这里的基本原理是将事件处理程序添加到父对象,在本例中为<div id="lists"></div>。然后,在触发事件时,您查询该事件的目标以查看其是否与您的元素匹配。

使用此技术,在添加新项目时不必重新绑定事件处理程序,如果通过用户交互添加项目,则特别有用。

对于您来说,它看起来像:

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');

   //Now that the parent element is added to the DOM
   //Add the event handler
   lists.addEventListener("click",function(e) {
   // e.target was the clicked element
   if (e.target && e.target.matches(".list")) {
       listNav.listNav(obj.name);
       listSidebarL.listSidebarL();
       listSidebarR.listSidebarR();
       listMain.listMain(obj.items);
   }

   //Add Items etc    
});

注意 ScotsevalinnerHTML的评论同样适用于此答案。