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

#javascript #html #function #ecmascript-6 #event-listener

#javascript #HTML #функция #ecmascript-6 #прослушиватель событий

Вопрос:

Я печатаю простую строку на экране. При нажатии на одну из ее букв is следует удалять из любой строки и добавлять в конце. После того, как я нажимаю на одну букву, и новая строка печатается на странице, буквы не сохраняют свои прослушиватели событий. Это код 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 повторного добавления на страницу слушатели событий переназначались?

Комментарии:

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

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

3. @Bergi вы имеете в виду этот синтаксис () => {} ?

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

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

Ответ №1:

Если вы хотите переместить буквенный узел в конец, вы можете использовать свойство 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

Ответ №2:

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

 // 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.log("you clicked button#bttn1");
  } else if (origin.closest("#bttn2")) {
    console.log("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;
}