首页 > 解决方案 > 一个基本的 Javascript Todo 应用程序在 ForLoop 中表现得很奇怪

问题描述

我试图用 HTML、CSS 和 JS 制作自己的 TODO 应用程序。一切都按预期工作,除了这个奇怪的问题:

当我添加一个待办事项时,forloop 会将 addEventListener 放在它上面,所以当我点击它时,它将启动里面的任何代码

问题:如果我创建了多个待办事项 .. 某些项目停止工作(当我单击该项目时 addEventListener 不工作)。

就像我创建 1 个项目: item1 :工作。

如果我创建 2 个项目: item1:不工作。项目2:工作。

如果我创建 3 个项目: item1:工作。项目2:不工作。项目2:工作。...ETC。任何解释如何解决!

代码

<div id="form">
 <p id="error">Fill The Empty !</p>
<input id="input" type="text" placeholder="Text Here!" >
  <button id="add" type="submit" onclick="addIt()">Add</button>
</div>  
<div id="listContainer">
  <ul id="list">    

  </ul>
  <p id="noItems">You Have No Items!</p>  
</div>

CSS 代码

margin: 0px;
padding: 0px;
font-family: monospace, sans-serif;
list-style: none;
font-size: 10pt;
box-sizing: border-box;
}
#form{
display: flex;
flex-direction: column;
justify-content: center;
align-items:center;
}
#error{
color: red;
display: none;
margin: 5px 0px;
}
#input{
width: 95%;
height: 40px;
text-align: center;
margin: 5px 0px;
border: 1px purple dashed;
}
#add{
height: 40px;
width: 95%;
border: 0px;
color: white;
background-color: purple;
font-weight: 900;
}
#add:active{
color: purple;
background-color: white;
}
#listContainer{
margin-top: 40px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
}
#list{
display: flex;
flex-direction: column-reverse;
justify-content: center;
align-items: center;
width: 100vw;
}
.item{
position: relative;
text-align: center;
padding: 10px;
margin: 5px;
width: 95%;
color: purple;
background-color: white;
border: 1px purple solid;
font-size: 11pt;
}
.delete{
position: absolute;
right: 0px;
top: 0px;
padding: 10px;
width: 50px;
color: white;
background-color: red;
font-size: 11pt;
font-weight: 900;
}
#noItems{
color: lightgray;
margin-top: 50px;
/*display: none;*/
}

JS代码

let storeInput = "";

function addIt(){
/*---addIT() start---*/
  let input = document.getElementById("input");
  storeInput = input.value;
  if(storeInput == ""){
    let errorMsg = document.getElementById("error");
    errorMsg.style.display = "block";
    setTimeout(function(){errorMsg.style.display = "none";}, 2000)
  }else{
    input.value = "";
    let item = document.createElement("LI");
    item.className = "item";
    item.innerHTML = storeInput;
    let list = document.getElementById("list");
    list.appendChild(item); 
    let deleteIt = document.createElement("I");
    deleteIt.className = "delete";
    deleteIt.innerHTML = "X";
    item.appendChild(deleteIt);
  }
  let allItems = document.querySelectorAll(".item");
  for(var i = 0; i < allItems.length; i++){
    allItems[i].addEventListener("click", function(){
      if(this.style.textDecoration == "line-through"){
        this.style.textDecoration = "none";
      }else{
        this.style.textDecoration = "line-through";
      }
    })
  }
  let deleteItem = document.querySelectorAll(".delete");
  for(var j = 0; j < deleteItem.length; j++){
    deleteItem[j].addEventListener("click", function(){
      var deleteIt = this.parentElement;
      deleteIt.remove();
    })
  }
  document.querySelectorAll(".item").length;
  if(allItems.length == 0){
    document.getElementById("noItems").style.display = "block";
  }else{
    document.getElementById("noItems").style.display = "none";
  }
/*---addIT() end---*/}

如果您想现场试用该应用程序: https ://codepen.io/Salsa_Project/pen/NVWPaY?editors=0110

和 TY 提前。

标签: javascriptarraysfor-loop

解决方案


让我们以这个片段为例

  for(var j = 0; j < deleteItem.length; j++){
    deleteItem[j].addEventListener("click", function(){
      var deleteIt = this.parentElement;
      deleteIt.remove();
    })
  }

在这里,您正在运行一个循环,并且 foreach 迭代,您正在创建一个新的点击事件。这里的问题是您没有解除绑定事件。因此,在您当前的代码中,如果您单击按钮,它将触发之前触发的所有呼叫事件。

您的代码最快的解决方案是添加类似

let deleteItem = document.querySelectorAll(".delete");
  for(var j = 0; j < deleteItem.length; j++){
     deleteItem[j].parentNode.replaceChild(deleteItem[j].cloneNode(true), deleteItem[j]);
    })
  }
 deleteItem = document.querySelectorAll(".delete");
  for(var j = 0; j < deleteItem.length; j++){
    deleteItem[j].addEventListener("click", function(){
      var deleteIt = this.parentElement;
      deleteIt.remove();
    })
  }

注意

  for(var j = 0; j < deleteItem.length; j++){
     deleteItem[j].parentNode.replaceChild(deleteItem[j].cloneNode(true), deleteItem[j]);
    })
  }

将用它自己替换你当前的元素。唯一的区别是,cloneNode 不会复制事件侦听器。这解决了你的问题。


推荐阅读