简体   繁体   中英

Event listeners don't get re-attached to my HTML elements when using ES6 without re-feshing the page

I am printing a simple string to the screen. When clicking on one of its letters, is should be removed from wherever it is the string and added at the end. After I click on one letter and the new string is getting printed to the page, the letters don't preserve their event listeners. This is the JS code and here is all the code 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));

I tried moving the even assignments (this block)

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

inside printArrayToPage function but because I am using ES6 syntax, I can't use a function before its definition. If I change to functions created used the function keyword, everything works as expected. How can I fix this issue using ES6 so that after I click on a letter and the divs get re-added to the page, event listeners are re-assigned?

If you want to move the letter node to the end, you can use the Node.parentNode property, and append the child node to the end. You don't need to create the nodes every time an item is clicked:

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

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

Use event delegation . Here's a simple example snippet:

 // 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; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM