繁体   English   中英

使用 Javascript 在 DOM 中添加新元素的问题

[英]Issue with Adding New Element in the DOM with Javascript

我是 javascript 的新手,我正在尝试使用 HTML、CSS 和 Z9E13B69D1D74DA927Z102ACAAAF 创建购物清单基本上,它上面已经有一个预先存在的列表,但是您可以通过在输入字段中键入新列表来添加一个新列表,然后按删除按钮将其删除。

我正在尝试添加一个函数( emptyList() ),该函数在列表为空时添加一个内容为“空列表”的 h2 元素。 但是,如果您事先在列表中添加了超过 1 个项目,然后将其删除,则取决于您添加了多少列表,添加的 h2 元素也与列表的数量相同。

我现在在deleteListElement() function 中调用了emptyList() function。 我尝试在它之外调用它,以及在 createListElement () function 上调用它。

期望:在此处输入图像描述

实际:在此处输入图像描述

暂时忽略 CSS。

这是我的代码:

 var addButton = document.getElementById("addButton"); var input = document.getElementById("userinput"); var ul = document.querySelector("ul"); var li = document.getElementsByTagName("li"); var deleteButton = document.getElementsByClassName("deleteButton"); var i = document.getElementsByTagName("i"); var secondSection = document.querySelector('.second-section'); function inputLength() { return input.value.length; } function deleteElement() { var h2 = document.querySelector("h2"); if (li.length > 0){ h2.parentNode.removeChild(h2); } } // for (let index = 0; index == li.length; index++) { // if (li.length == 0){ // h2[index].remove(); // } // } function createListElement() { //add list var li = document.createElement("li"); li.append(document.createTextNode(input.value)); li.classList.add("item", "zone"); li.addEventListener("click", crossOutListWhenClicked); ul.appendChild(li); input.value = ""; //resets the input field addDeleteButtonToList(); deleteElement(); function addDeleteButtonToList(){ var button = document.createElement("deleteButton"); var i = document.createElement("i"); i.classList.add("fa-solid", "fa-trash-can"); button.classList.add("deleteButton"); button.appendChild(i); button.addEventListener('click', deleteListElement); li.appendChild(button); } } function deleteListElement(){ var deletes = document.querySelectorAll('.deleteButton'); // Iterate all nodes deletes.forEach(btn => { // Attach event listener. Note to preserve the button this-reference // by using the non-shorthand function btn.addEventListener('click', function() { var li = this.parentNode li.remove(); EmptyList(); }) }) } function addListAfterClick() { if (inputLength() > 0) { createListElement(); } } function addListAfterKeypress(event) { if (inputLength() > 0 && event.keyCode === 13) { createListElement(); } } function crossOutListWhenClicked(){ var li = document.querySelectorAll("li"); // for (let index = 0; index < li.length; index++) { // li[index].addEventListener("click", function(){ li.forEach(x => x.addEventListener("click", function(){ x.classList.toggle('done'); })) } function EmptyList(){ var h2 = document.createElement("h2"); if (li.length == 0){ secondSection.appendChild(h2); h2.append(document.createTextNode("Empty List")); console.log(h2); } } deleteListElement(); crossOutListWhenClicked(); addButton.addEventListener("click", addListAfterClick); input.addEventListener("keypress", addListAfterKeypress);
 body { margin: auto 20rem; height: 100%; }.container { background-color: #E38B29; margin: 0 auto; }.zone { display: flex; cursor: pointer; background-color: white; font-size: 1em; border: 0; transition: all 0.3s linear; } #main-head { color: #FDEEDC; display: flex; justify-content: center; align-items: center; border: none; border-radius: 0; height: 10vh; }.first-section { display: flex; align-items: center; justify-content: center; font-size: 2em; height: 10vh; border: none; border-radius: 0; }.second-section { height: 80vh; border-radius: 20px 20px 0px 0px; border-color: white; border: 2px solid #E38B29; } ul{ display: flex; justify-content: flex-start; align-items: flex-start; flex-wrap: wrap; flex-direction: column; height: 100%; overflow: auto; margin-top: 15px; background-color: #E38B29; list-style: none; padding: 0; } ul >.zone{ border: none; } h2{ margin: 0 auto; } li{ margin-left: 20px; }.gradient { background-color: #E38B29; }.done { text-decoration: line-through; }
 <.DOCTYPE html> <html> <head> <title>Javascript + DOM</title> <link rel="stylesheet" type="text/css" href="style:css"> <link rel="stylesheet" href="https.//cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css"> </head> <body> <div class="container"> <header class="zone gradient" id="main-head"> <h1>Shopping List</h1> </header> <section class="zone first-section gradient"> <!-- <p id="first">Get it done today</p> --> <input id="userinput" type="text" placeholder="enter items"> <button id="addButton">Enter</button> </section> <section class="zone second-section"> <ul class="zone"> <li class="item zone">Notebook <button class="deleteButton"><i class="fa-solid fa-trash-can"></i></button> </li> <li class="item zone">Apple <button class="deleteButton"><i class="fa-solid fa-trash-can"></i></button> </li> </ul> </section> <script type="text/javascript" src="script.js"></script> </div> </body> </html>

问题是deleteListElement 这个 function 在页面加载时被调用,以在所有现有的删除按钮上附加点击处理程序。

但是,您还可以使用此 function 作为新删除按钮上的事件处理程序。 本身添加事件处理程序的事件处理程序通常是代码异味。 而且在这里,这是错误的。 这意味着当用户添加一个新项目时,所有现有的删除按钮也会获得一个新的点击处理程序。 因此,这些按钮获得了不止一个点击处理程序,这就解释了为什么您会获得这些多个“空列表”标题。

所以把这个 function 一分为二:

  • 一个 function 只需处理一个按钮的点击。
  • 另一个 function 用于处理页面加载时已经存在的按钮。

不相关,但deleteElement也存在问题:它应该检查h2元素是否存在。 如果没有,它应该什么都不做。

我已经在代码更改的地方添加了注释。 虽然我没有测试其他问题...我只是关注您提出的问题以及在添加项目时立即导致错误的问题(我提到的关于缺少h2元素的问题)。

 var addButton = document.getElementById("addButton"); var input = document.getElementById("userinput"); var ul = document.querySelector("ul"); var li = document.getElementsByTagName("li"); var deleteButton = document.getElementsByClassName("deleteButton"); var i = document.getElementsByTagName("i"); var secondSection = document.querySelector('.second-section'); function inputLength() { return input.value.length; } function deleteElement() { var h2 = document.querySelector("h2"); // Add a condition to see H2 exists if (h2 && li.length > 0){ h2.parentNode.removeChild(h2); } } function createListElement() { var li = document.createElement("li"); li.append(document.createTextNode(input.value)); li.classList.add("item", "zone"); li.addEventListener("click", crossOutListWhenClicked); ul.appendChild(li); input.value = ""; addDeleteButtonToList(); deleteElement(); function addDeleteButtonToList(){ var button = document.createElement("deleteButton"); var i = document.createElement("i"); i.classList.add("fa-solid", "fa-trash-can"); button.classList.add("deleteButton"); button.appendChild(i); // Call common function to attach ONE handler activateDeleteAction(button); li.appendChild(button); } } // New function. Common for 2 use cases: // - for existing delete buttons, on page load // - for newly added delete buttons, on user action function activateDeleteAction(btn) { btn.addEventListener('click', function() { var li = this.parentNode; li.remove(); EmptyList(); }) }; // Renamed this function: function activateAllDeleteActions(){ var deletes = document.querySelectorAll('.deleteButton'); // Use other function to attach handler deletes.forEach(activateDeleteAction); } function addListAfterClick() { if (inputLength() > 0) { createListElement(); } } function addListAfterKeypress(event) { if (inputLength() > 0 && event.keyCode === 13) { createListElement(); } } function crossOutListWhenClicked(){ var li = document.querySelectorAll("li"); li.forEach(x => x.addEventListener("click", function(){ x.classList.toggle('done'); })) } function EmptyList(){ var h2 = document.createElement("h2"); if (li.length == 0){ secondSection.appendChild(h2); h2.append(document.createTextNode("Empty List")); } } activateAllDeleteActions(); // Calling renamed function crossOutListWhenClicked(); addButton.addEventListener("click", addListAfterClick); input.addEventListener("keypress", addListAfterKeypress);
 body { margin: auto 20rem; height: 100%; }.container { background-color: #E38B29; margin: 0 auto; }.zone { display: flex; cursor: pointer; background-color: white; font-size: 1em; border: 0; transition: all 0.3s linear; } #main-head { color: #FDEEDC; display: flex; justify-content: center; align-items: center; border: none; border-radius: 0; height: 10vh; }.first-section { display: flex; align-items: center; justify-content: center; font-size: 2em; height: 10vh; border: none; border-radius: 0; }.second-section { height: 80vh; border-radius: 20px 20px 0px 0px; border-color: white; border: 2px solid #E38B29; } ul{ display: flex; justify-content: flex-start; align-items: flex-start; flex-wrap: wrap; flex-direction: column; height: 100%; overflow: auto; margin-top: 15px; background-color: #E38B29; list-style: none; padding: 0; } ul >.zone{ border: none; } h2{ margin: 0 auto; } li{ margin-left: 20px; }.gradient { background-color: #E38B29; }.done { text-decoration: line-through; }
 <.DOCTYPE html> <html> <head> <title>Javascript + DOM</title> <link rel="stylesheet" type="text/css" href="style:css"> <link rel="stylesheet" href="https.//cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css"> </head> <body> <div class="container"> <header class="zone gradient" id="main-head"> <h1>Shopping List</h1> </header> <section class="zone first-section gradient"> <!-- <p id="first">Get it done today</p> --> <input id="userinput" type="text" placeholder="enter items"> <button id="addButton">Enter</button> </section> <section class="zone second-section"> <ul class="zone"> <li class="item zone">Notebook <button class="deleteButton"><i class="fa-solid fa-trash-can"></i></button> </li> <li class="item zone">Apple <button class="deleteButton"><i class="fa-solid fa-trash-can"></i></button> </li> </ul> </section> <script type="text/javascript" src="script.js"></script> </div> </body> </html>

暂无
暂无

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

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