一个基本的Java Todo应用程序在ForLoop中表现不佳

时间:2019-05-05 16:57:41

标签: javascript arrays for-loop

我正在尝试使用HTML,CSS和JS制作自己的TODO应用程序。一切都按预期工作,解决了这个奇怪的问题:

当我添加待办事项时,forloop会在其上添加addEventListener,因此当我单击它时,它将启动内部的任何代码

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

就像我创建1个项目一样: item1:正在工作。

如果我创建2个项目: item1:不起作用。 item2:正在工作。

如果我创建3个项目: item1:正在工作。 item2:不起作用。 item2:正在工作。 ...等等。 任何说明如何解决!

HTML代码

<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

提前付款。

2 个答案:

答案 0 :(得分:1)

让我们以该代码段为例

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

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

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

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不复制事件侦听器。这样可以解决您的问题。

答案 1 :(得分:1)

函数addit()会在所有元素上添加事件监听器,并在每次添加元素时删除按钮。您只应将事件侦听器添加到当前项目。 codepen

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);
    item.addEventListener("click", function(){
      if(this.style.textDecoration == "line-through"){
        this.style.textDecoration = "none";
      }else{
        this.style.textDecoration = "line-through";
      }
    });
    deleteIt.addEventListener("click", function(){
      var deleteIt = this.parentElement;
      deleteIt.remove();
    })
  }
  let allItems = document.querySelectorAll(".item");


  document.querySelectorAll(".item").length;
  if(allItems.length == 0){
    document.getElementById("noItems").style.display = "block";
  }else{
    document.getElementById("noItems").style.display = "none";
  }
/*---addIT() end---*/}