Слушатели событий не прикрепляются к моим элементам HTML при использовании ES6 без повторной загрузки страницы

Я печатаю простую строку на экране. При нажатии на одну из ее букв следует удалить ее из строки и добавить в конец. После того, как я нажимаю на одну букву, и новая строка печатается на странице, буквы не сохраняют свои прослушиватели событий. Это код JS и вот весь код https://codesandbox.io/s/reverse-array-forked-fvclg?file=/src/index.js:0-1316:

const appBox = document.getElementById("app");

const convertString = (string) => {
  let stringToArray = string.split("");
  return stringToArray;
};

let stringToArray = convertString("Hello world!");

const printArrayToPage = (string) => {
  string.forEach((element) => {
    const textBox = document.createElement("div");

    if (element !== " ") {
      textBox.classList.add("letter");
    } else {
      textBox.classList.add("emptySpace");
    }

    const text = document.createTextNode(element);
    textBox.appendChild(text);
    appBox.appendChild(textBox);
  });
};

window.onload = printArrayToPage(stringToArray);

const moveLetter = (event) => {
  const targetLetter = event.target;
  const letterToRemove = targetLetter.innerHTML;
  targetLetter.classList.add("invisible");

  if (stringToArray.includes(letterToRemove)) {
    const index = stringToArray.indexOf(letterToRemove);
    stringToArray.splice(index, 1);
  }

  stringToArray.push(letterToRemove);
  appBox.innerHTML = "";
  printArrayToPage(stringToArray);
};

const allLetters = document.querySelectorAll(".letter");
allLetters.forEach((element) => element.addEventListener("click", moveLetter));
const allSpaces = document.querySelectorAll(".emptySpace");
allSpaces.forEach((element) => element.addEventListener("click", moveLetter));

Я попытался переместить четные задания (этот блок)

const allLetters = document.querySelectorAll(".letter");
allLetters.forEach((element) => element.addEventListener("click", moveLetter));
const allSpaces = document.querySelectorAll(".emptySpace");
allSpaces.forEach((element) => element.addEventListener("click", moveLetter));

внутри функции printArrayToPage, но поскольку я использую синтаксис ES6, я не могу использовать функцию до ее определения. Если я перейду к функциям, созданным с использованием ключевого слова function, все будет работать так, как ожидалось. Как я могу исправить эту проблему с помощью ES6, чтобы после нажатия на букву и повторного добавления divs на страницу прослушиватели событий переназначались?

Предлагаем вам изучить, как использовать «делегирование событий»

charlietfl 19.12.2020 15:13

Почему бы просто не использовать объявления ES6 function? Они более декларативны, немного короче и действительно работают.

Bergi 19.12.2020 17:19

@ Берги, ты имеешь в виду этот синтаксис () => {}?

user4491949 19.12.2020 17:48

@AriO Я имею в виду синтаксис function moveLetter(event) {…}

Bergi 19.12.2020 17:52

@Bergi Берги Я думал, что это просто объявление стандартной функции? В ES6 появились толстые стрелочные функции, не так ли?

user4491949 19.12.2020 17:57

@charlietfl спасибо, на самом деле это то, о чем я не знал, поэтому теперь я могу об этом прочитать. Очень признателен.

user4491949 19.12.2020 17:58

@AriO Стандарт ES6 также представил новые функции для объявлений function. «Использование ES6» не означает ограничение себя самыми последними языковыми дополнениями.

Bergi 19.12.2020 17:59

@Bergi Берги, я почитаю об этом подробнее, спасибо. Честно говоря, в 95% случаев я использую стрелочные функции до такой степени, что обычные выглядят странно.

user4491949 19.12.2020 18:04
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
8
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если вы хотите переместить узел с буквой в конец, вы можете использовать свойство Node.parentNode и добавить дочерний узел в конец. Вам не нужно создавать узлы каждый раз, когда нажимается элемент:

const moveLetter = (event) => {
  const targetLetter = event.target;
  const parent = targetLetter.parentNode;
  parent.appendChild(targetLetter); // move the element to the end
};

См.: https://codesandbox.io/s/reverse-array-forked-lf333?file=/src/index.js

Используйте делегирование событий. Вот простой пример фрагмента:

// adding an event listener to the document
document.addEventListener("click", evt => {
  console.clear();
  const origin = evt.target;
  //             ^ where did the event originated?
  if (origin.closest("#bttn1")) {
    console.info("you clicked button#bttn1");
  } else if (origin.closest("#bttn2")) {
    console.info("you clicked button#bttn2")
  }
});

createElement("h3", "header", "Wait 2 seconds...");

// creating buttons after a while. The earlier created
// event listener will detect clicks for the new buttons
setTimeout( () => {
    createElement("button", "bttn1", "click me");
    createElement("button", "bttn2", "click me too");
  }, 2000);

function createElement(nodetype, id, text) { 
  document.body.appendChild(
    Object.assign(document.createElement(nodetype), {id, textContent: text})
  );
}
body {
  font: normal 12px/15px verdana, arial;
  margin: 2rem;
}
button {
  margin: 0 0.6rem 0 0;
}

Другие вопросы по теме