код forEach не работает, но один и тот же код в двух разных функциях forEach работает, почему? - PullRequest
0 голосов
/ 16 января 2019

У меня есть массив с именем FilterTasks, для каждой задачи я хочу создать кнопку в Div и добавить к ней функцию onclick. Я создал некоторый код (который вы можете увидеть ниже, первый блок), чтобы сделать это. Что не сработало, кнопки создаются правильно, но функция onclick добавляется только к последней кнопке. Когда я использую один и тот же код, но делится на 2 различных обратных вызова forEach (которые вы также можете просмотреть ниже, вторая часть), это работает. Короче говоря, при попытке создать кнопки и добавить к ним функцию onclick при создании только последняя кнопка должным образом получает функцию onclick. Но когда я сначала создаю все кнопки, а затем добавляю функцию onclick для каждой, она работает. Я не могу понять, почему это так. Любой лучший разработчик, который может указать мне, почему? Большое спасибо!

        filteredTasks.forEach(function(task) {
            var buttonId = task.taskName.replace(/\s/g, '') + 'Button'
            var taskHTML = `<button class="taskButton" id="${buttonId}">${task.taskName}</button>`;
            taskDiv.innerHTML += taskHTML;
            var button = document.querySelector(`#${buttonId}`);
            button.onclick = function() {performTask(task)};
        });
    };





        filteredTasks.forEach(function(task) {
            var buttonId = task.taskName.replace(/\s/g, '') + 'Button'
            var taskHTML = `<button class="taskButton" id="${buttonId}">${task.taskName}</button>`;
            taskDiv.innerHTML += taskHTML;
        });

        filteredTasks.forEach(function(task) {
            var buttonId = task.taskName.replace(/\s/g, '') + 'Button'
            var button = document.querySelector(`#${buttonId}`);
            button.onclick = function() {performTask(task)};
        });
    };

1 Ответ

0 голосов
/ 16 января 2019

Я подозреваю, что это связано с тем, как вы обрабатываете обновления DOM. Ваш код только добавляет событие к последней кнопке. Это известная проблема с for/loop s ). Использование forEach вместо for / loop обычно исправляет это , но, очевидно, не в этом случае. (Я ценю, что это немного волнисто. У другого члена SO может быть более подробная техническая причина, почему это не работает в этом случае.)

Тем не менее, как вы обнаружили, вам гораздо лучше делать это поэтапно, но вы должны пойти еще на несколько шагов дальше. Это позволит избежать попадания в ситуацию, в которой вы сейчас находитесь, и будет более производительным.

В данный момент вы пытаетесь достичь всего за один цикл: создание html-задачи, добавление ее в DOM и добавление прослушивателя событий для новой кнопки. Что вам нужно сделать, это создать all HTML, затем добавить that в DOM, затем взять все кнопки сразу, используя их класс, и добавить к ним слушателей.

const filteredTasks = [{ taskName: 'bob' },{ taskName: 'dave' }];
const tasks = document.querySelector('#tasks');

// Use `map` to create all the buttons
// I've used a data attribute here instead of an actual id
const html = filteredTasks.map(task => {
  const buttonId = `${task.taskName.replace(/\s/g, '')}Button`;
  return `<button class="taskButton" data-id="${buttonId}">${task.taskName}</button>`;
}).join('');

// Add that HTML to the DOM with one update
tasks.innerHTML = html;

// Grab all the taskButton buttons using their class,
// and add click listeners to them
const buttons = document.querySelectorAll('.taskButton');
[...buttons].forEach(button => button.addEventListener('click', performTask, false));

// `performTask` destructs the event target (clicked button)
// and logs the id 
function performTask(e) {
  const { dataset: { id } } = e.target;
  console.log(id);
}
<div id="tasks"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...