Как я могу добавитьEventListener для каждого innerHTML + = в этом для цикла? - PullRequest
0 голосов
/ 10 апреля 2019

Я пытаюсь добавить прослушиватель событий для некоторых повторяющихся innerHTML.IE для каждой партии HTML, добавленной innerHTML, мне также нужно добавить в нее событие click.

Чтобы усложнить задачу, я также импортирую набор данных из другого файла JS, импортированного под именем name.Как вы можете видеть из кода, мне нужно, чтобы данные внутри прослушивателя событий были специфичны для итерации цикла for для innerHTML, чтобы при запуске прослушивателя событий я мог видеть правильные соответствующие данные.

Этомоя попытка:

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 ]

2 голосов
/ 10 апреля 2019

Вам нужно переместить код, который устанавливает обработчики событий, так, чтобы он находился вне вашего цикла for и выполнялся после его завершения.Затем вместо .querySelector(), который возвращает только первый соответствующий элемент, вам нужно .querySelectorAll(), чтобы вернуть все соответствующие элементы.После этого вы будете перебирать все эти элементы и настраивать обработчик.

Вам также необходимо изменить способ объявления переменной obj, чтобы она находилась в области действия вне * 1006.* петля.Сделайте это, объявив его непосредственно перед циклом, но назначив его внутри цикла:

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 для создания новых элементов, их настройки и внедрения в DOM.Если вы должны использовать .innerHTML, то создайте строку в вашем цикле, а после цикла вставьте строку в DOM через .innerHTML, только один раз.

0 голосов
/ 10 апреля 2019

Один из вариантов - посмотреть на событие делегирование / пузыри .Основным принципом здесь является добавление обработчика событий к родительскому объекту, в данном случае <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    
});

ПРИМЕЧАНИЕ шотландцы комментарии re eval и innerHTML в равной степени применимы к этому ответу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...