简体   繁体   English

javascript - for 循环 - 仅每隔一个事件监听器工作

[英]javascript - for loop - only every second event listener working

I am very new to web design so im sure im doing something silly here but i am really curious what i am doing wrong, I am doing an online udemy course and for some reason only every second iteration of the li's that i spawn appear to have my event listener attached and i cannot for the life of me figure out why.我对 web 设计非常陌生,所以我确定我在这里做了一些愚蠢的事情,但我真的很好奇我做错了什么,我正在做一个在线 udemy 课程,由于某种原因,我生成的 li 的每一次迭代似乎都有我的事件监听器已附加,我无法为我的生活找出原因。 I am assuming it is something todo with my "this" when adding the event listener, i tried to change to a listObjects[i].classList.toggle but it just threw an error however strangely enough if i do a this.classList.add("done") it works perfectly.我假设在添加事件侦听器时它与我的“this”有关,我试图更改为 listObjects[i].classList.toggle 但它只是抛出了一个错误,但是如果我执行 this.classList.add 就足够奇怪了(“完成”)它完美地工作。 thanks in advance!提前致谢!

 var enterBtn = document.querySelectorAll("button")[0]; var cancelBtn = document.querySelectorAll("button")[1]; var ul = document.querySelector("ul"); var listObjects function addList(todo) { var li = document.createElement("li"); li.appendChild(document.createTextNode(todo)); ul.appendChild(li); listObjects = document.querySelectorAll("li"); setListDone(); } enterBtn.addEventListener("click", function() { var listData = document.querySelector("input").value; addList(listData); }); cancelBtn.addEventListener("click", function() { ul.innerHTML = " "; }); function setListDone() { for (i = 0; i < listObjects.length; i++) { listObjects[i].addEventListener("click", function() { this.classList.toggle("done"); }); } }
 .done { text-decoration: line-through; }
 <h1>Todo List</h1> <input type="text"> <button>Enter</button> <button>Cancel</button> <ul> </ul>

You're never removing the old event listeners, so anything with an even index is getting toggled twice (or four times, or whatever) and ending up in the same state as it started.您永远不会删除旧的事件侦听器,因此任何具有偶数索引的东西都会被切换两次(或四次,或其他任何东西)并最终以与开始时相同的 state 结束。 If you clear the old event listener first (or only add them to newly created elements) the issue disappears:如果您先清除旧的事件侦听器(或仅将它们添加到新创建的元素中),问题就会消失:

 var enterBtn = document.querySelectorAll("button")[0]; var cancelBtn = document.querySelectorAll("button")[1]; var ul = document.querySelector("ul"); var listObjects function addList(todo) { var li = document.createElement("li"); li.appendChild(document.createTextNode(todo)); ul.appendChild(li); listObjects = document.querySelectorAll("li"); setListDone(); } enterBtn.addEventListener("click", function() { var listData = document.querySelector("input").value; addList(listData); }); cancelBtn.addEventListener("click", function() { ul.innerHTML = " "; }); function setListDone() { for (i = 0; i < listObjects.length; i++) { listObjects[i].removeEventListener("click", liClickHandler); listObjects[i].addEventListener("click", liClickHandler); } } function liClickHandler() { this.classList.toggle("done"); }
 .done { text-decoration: line-through; }
 <h1>Todo List</h1> <input type="text"> <button>Enter</button> <button>Cancel</button> <ul> </ul>

The reason is you are using setListDone to assign click to all li .原因是您使用setListDoneclick分配给所有li So when you add second li it will assign click to first li also.因此,当您添加第二个li时,它也会将click分配给first li So when you click on first li it will call click twice .因此,当您单击第一个li时,它将调用click twice Further if you add third li then on first li click it will call click three times .此外,如果您添加第三个li ,那么在first li单击时,它将调用click three times

To solve issue you just need to pass newly created li to setListDone and update your setListDone as below.要解决问题,您只需将新创建的li传递给setListDone并更新您的setListDone ,如下所示。

function setListDone(li) {
  li.addEventListener("click", function() {
    this.classList.toggle("done");
  });
}

Test complete code below.测试下面的完整代码。

 var enterBtn = document.querySelectorAll("button")[0]; var cancelBtn = document.querySelectorAll("button")[1]; var ul = document.querySelector("ul"); var listObjects function addList(todo) { var li = document.createElement("li"); li.appendChild(document.createTextNode(todo)); ul.appendChild(li); listObjects = document.querySelectorAll("li"); setListDone(li); } enterBtn.addEventListener("click", function() { var listData = document.querySelector("input").value; addList(listData); }); cancelBtn.addEventListener("click", function() { ul.innerHTML = " "; }); function setListDone(li) { li.addEventListener("click", function() { this.classList.toggle("done"); }); }
 .done { text-decoration: line-through; }
 <h1>Todo List</h1> <input type="text"> <button>Enter</button> <button>Cancel</button> <ul> </ul>

Every time you add item to the list you add event listeners to every item.每次将项目添加到列表时,都会为每个项目添加事件侦听器。 That's why some of the are trigged twice or event more.这就是为什么其中一些被触发两次或更多事件的原因。

listObjects[i].addEventListener("click", function() {
  this.classList.toggle("done");
});

the simple solution is below.简单的解决方案如下。

you just need to add event listener to a single <li> every time you add element to the list.每次将元素添加到列表时,您只需要将事件侦听器添加到单个<li>

 var enterBtn = document.querySelectorAll("button")[0]; var cancelBtn = document.querySelectorAll("button")[1]; var ul = document.querySelector("ul"); var listObjects function addList(todo) { var li = document.createElement("li"); li.appendChild(document.createTextNode(todo)); // Here you add the listener to just created list item li.addEventListener("click", function() { this.classList.toggle("done"); }); ul.appendChild(li); } enterBtn.addEventListener("click", function() { var listData = document.querySelector("input").value; addList(listData); }); cancelBtn.addEventListener("click", function() { ul.innerHTML = " "; });
 .done { text-decoration: line-through; }
 <h1>Todo List</h1> <input type="text"> <button>Enter</button> <button>Cancel</button> <ul> </ul>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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