在所有创建的 li 元素上添加事件监听器

问题描述 投票:0回答:7

所以我有一个简单的脚本,将“li”元素添加到“ul”并为它们分配一个类。现在我想更改点击事件上的“li”项目的类。

这是 HTML:

<form class="form">
<input id="newInput" type="text" placeholder="Dodaj pozycję">
<button id="createNew" type="button">Dodaj</button>
</form>
<h2>Moja lista:</h2>
<div class="listBg">
<ul id="list">
</ul>
</div>
<button id="deleteAll" type="button">Wyczyść</button>

JS:

function addItem() {
    var myList = document.getElementById("list"); // get the main list ("ul")
    var newListItem = document.createElement("li"); //create a new "li" element
    var itemText = document.getElementById("newInput").value; //read the input value from #newInput
    var listText = document.createTextNode(itemText); //create text node with calue from input
    newListItem.appendChild(listText); //add text node to new "li" element
    if (itemText === "") { // if input calue is empty
        alert("Pole nie może być puste"); // show this alert
    } else { // if it's not empty
        var x = document.createElement("span"); // create a new "span" element
        x.innerText = "X"; // add inner text to "span" element
        x.className = "closer"; // add class to "span" element
        myList.appendChild(newListItem); // add created "li" element to "ul"
        newListItem.className = "item"; // add class to new "li" element
        newListItem.appendChild(x); // add a "span" to new "li" element
        var itemText = document.getElementById("newInput"); // read current input value
        itemText.value = ""; // set current input calue to null
    }
};

我想这样的事情应该可以解决问题,但它不起作用:

function itemDone() {
    var listItems = document.querySelectorAll("li");
    var i;
    for (i = 0; i < listItems.length; i++) {
    listItem[i].className = "itemDone";
};
};

var item = document.getElementsByClassName("item");
item.addEventListener("click", itemDone);

我对 javascript 相当陌生,所以我希望能得到一些解释和答案。

javascript html css
7个回答
26
投票

对动态创建的元素使用事件委托。这样,您只需要

ul#list
上的一个事件侦听器,它将适用于您动态附加到它的所有元素:

document.getElementById("list").addEventListener("click",function(e) {
  if (e.target && e.target.matches("li.item")) {
    e.target.className = "foo"; // new class name here
    }
});

这是一个简化的示例,您可以了解代码会发生什么:

function addItem(i) {
  var li = document.createElement('li');
  li.appendChild(document.createTextNode(i));
  li.className = 'item';
  document.getElementById('list').appendChild(li);
}

var counter = 2;
document.getElementById('btn').addEventListener('click', function() {
  addItem(counter++);
});

document.getElementById("list").addEventListener("click", function(e) {
  if (e.target && e.target.matches("li.item")) {
    e.target.className = "foo"; // new class name here
    alert("clicked " + e.target.innerText);
  }
});
<ul id="list">
  <li class="item">1</li>
</ul>

<button id="btn">
  add item
</button>


3
投票

您必须在每个单个项目上设置事件监听器,因为

document.getElementsByClassName()
返回一组项目,并且您不能简单地通过一次调用
addEventListener()
向所有项目添加事件侦听器。

因此,就像您在

itemDone()
中使用的循环一样,您必须迭代所有项目并向它们添加侦听器:

var items = document.getElementsByClassName("item");
for (var i = 0; i < items.length; i++) {
  items[i].addEventListener("click", itemDone);
}

正如评论中指出的,您也可以在创建元素时直接这样做,因此在您的

addItem()
函数中,添加:

newListItem.addEventListener("click", itemDone);

2
投票

试试这个:

var item = document.getElementsByClassName("item");
for (var i = 0; i < item.length; i++) {
  item[i].addEventListener("click", itemDone);
}

2
投票

function addItem(i) {
  var li = document.createElement('li');
  li.appendChild(document.createTextNode(i));
  li.className = 'item';
  document.getElementById('list').appendChild(li);
}

var counter = 2;
document.getElementById('btn').addEventListener('click', function() {
  addItem(counter++);
});

document.getElementById("list").addEventListener("click", function(e) {
  if (e.target && e.target.matches("li.item")) {
    e.target.className = "foo"; // new class name here
    alert("clicked " + e.target.innerText);
  }
});
<ul id="list">
  <li class="item">1</li>
  <li class="item">1</li>
  <li class="item">1</li>
  <li class="item">1</li>
  <li class="item">1</li>
</ul>

<button id="btn">
  add item
</button>


0
投票

首先,尝试使用

getElementByTagName
而不是
querySelectorAll
,因为
querySelectorAll
速度较慢。其次,
item
接收一个数组,因此
item.addEventListener
会给你一个错误。您必须在循环中对 item[counter] 执行 addEventListener。


0
投票
document.getElementById("list").addEventListener("click", function (e) {
        const parent = e.target.parentElement;
        const siblings = Array.from(parent.getElementsByTagName("LI"));
        siblings.forEach(n => (n.className = (e.target === n) ? "foo" : ""));
      });

0
投票

虽然@baoo 的答案是正确的,如果我们没有在 li 中嵌套 html 元素。但是,如果 li 中也有 HTML 元素,那么它将失败。

要处理这种情况,您可以使用下面的代码片段。这样您就不需要进行额外的检查。

const list = document.getElementById("list");
list.addEventListener("click",function(event) {
  event.target.closest("li.item").classList.add("foo");
});
© www.soinside.com 2019 - 2024. All rights reserved.