首页 > 解决方案 > How to target non-unique, dynamically generated elements in the DOM with plain javascript?

问题描述

I have an input field that pushes the inputted string into an array, then generates a <li> from each object in the array. I also have a click listener added to each list item as it is generated.

The click listener and the dynamically generated list items work as expected, except the only thing I can get the click listener's function to do is console.log, because I don't know how to target the list item that has just been clicked.

I want to target the clicked item to add a class that will change it's text-decoration to line-through. I have everything in place, I just need to figure out how to target the clicked item using the DOM.

I have tried document.querySelectorAll("li"), but that only returns a Nodelist. I have tried every other DOM method I can think of as well, I have tried passing this as an argument in the function when it is called. There is no way to make each generated list item unique, they all have the same class and the same parent.

If I target the first child by saying document.getElementByTagName("ul").firstChild.classList.add("strikethrough"); everything works, meaning the code is bug free, but that won't work when I have 10 list items and the 4th item is clicked.

I want to include my entire code, but I don't want to confuse the question, because there are many things going on from line to line, and each function is handling multiple processes. Again, I want to reiterate that everything works, I just am missing the final link, which is how to target this non-unique, dynamically generated element that has just been clicked on with DOM (or similar).

Here's the snippet in question, it should have everything you need to know about the code:

let plannerItems = [];
let backwardsArray = plannerItems.reverse();

function createList() {
  for (var i = 0; i < backwardsArray.length; i++) {
    var plannerItem = backwardsArray[i];
    var nextItem = document.createElement("li");
    nextItem.innerHTML= plannerItem;
    nextItem.classList.add("listItems");
    nextItem.addEventListener("click", function(event) {
      crossOff();
    });
    document.getElementById("list").prepend(nextItem);
  };
};

function crossOff() {
  document.getElementById("list").firstChild.classList.add("strikethrough");
   ////This is where I would put my DOM method....If I had one... ////
};

So, as you can see the very last line of code above the comment is the one I need to replace with the correct DOM method. I have also tried nextItem.classlist.add("strikethrough"); but that only adds the class to the first child, and not the clicked text.

标签: javascriptdomevent-listenerdynamically-generated

解决方案


You could access the element the element that was clicked upon from event using event.currentTarget, you could pass this into crossOff():

let plannerItems = ['One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten'];
let backwardsArray = plannerItems.reverse();

function createList() {
  for (var i = 0; i < backwardsArray.length; i++) {
    var plannerItem = backwardsArray[i];
    var nextItem = document.createElement("li");
    nextItem.innerHTML= plannerItem;
    nextItem.classList.add("listItems");
    nextItem.addEventListener("click", function(event) {
      crossOff(event.currentTarget);
    });
    document.getElementById("list").prepend(nextItem);
  };
};

function crossOff(item) {
  item.classList.add("strikethrough");
};

createList();
.strikethrough {
  text-decoration: line-through;
}

li {
  cursor: default;
}
<ul id="list">
</ul>


推荐阅读