我怎样才能使这个 JavaScript 代码更干净?

How can I can make this JavaScript code cleaner?

我是 JS 的新手,我为我正在学习的课程做了这个练习。基本上完成了,但我不得不重复创建“删除”按钮的代码,我不确定如何才能使它更干净。

var button = document.getElementById("add")
var input = document.getElementById("userinput")
var ul = document.querySelector("ul")
var li = document.querySelectorAll("li")

function inputLength() {
    return input.value.length;
}

function createListElement() {
    let li = document.createElement("li")
    li.appendChild(document.createTextNode(input.value))
    ul.appendChild(li)
    input.value = ""

    // Create a delete button and configure it:
    var btnDelete = document.createElement("button");
    btnDelete.classList.add("delete");
    btnDelete.textContent = "Delete";

    // Append the button to the list item
    li.appendChild(btnDelete);
}

// Create a delete button for each <li> already in the HTML file
li.forEach(function(item){
    var btnDelete = document.createElement("button");
    btnDelete.classList.add("delete");
    btnDelete.textContent = "Delete";
    item.appendChild(btnDelete);
 });

function addListAfterClick() {
    if(inputLength() > 0) {
        createListElement()
    }
}

function addListAfterKeypress(event) {
    if(inputLength() > 0 && event.keyCode === 13) {
        createListElement()
    }
}

button.addEventListener("click", addListAfterClick)

input.addEventListener("keypress", addListAfterKeypress)


function toggleClassDoneOnAndOff(event) {
    if (event.target.tagName === "LI") {
        event.target.classList.toggle("done");
    }
}

ul.addEventListener("click", toggleClassDoneOnAndOff);

function deleteAfterClick(event) {
    // Determine if it was a delete button that was clicked
    if(event.target.classList.contains("delete")){
      // Remove the closest li ancestor to the clicked element
      event.target.closest("li").remove();
    }
  
  }

// Handle all the clicks that originate from within the <ul> at
// the <ul> level when they bubble up to it instead of setting each
// button within the <ul> up with its own click event handler.
ul.addEventListener("click", deleteAfterClick);
.done {
    text-decoration: line-through;
}
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="Add items">
    <button id="add">Add</button>
    <ul id="ul">
        <li>Notebook</li>
        <li>Jello</li>
        <li>Spinach</li>
        <li>Rice</li>
        <li>Birthday Cake</li>
        <li>Candles</li>
    </ul>
    <script type="text/javascript" src="script.js"></script>
</body>

我的问题就这么简单,但由于 Stack Overflow 告诉我“添加更多详细信息”...

基本上,我试图将这部分变成一个函数:

var btnDelete = document.createElement("button");
btnDelete.classList.add("delete");
btnDelete.textContent = "Delete";

但我不知道如何让它在其他的里面工作。

您只需将这 3 行提取到它们自己的函数中,并使该函数 return 成为新创建的元素。现在这些行将被函数调用替换。

var button = document.getElementById("add")
var input = document.getElementById("userinput")
var ul = document.querySelector("ul")
var li = document.querySelectorAll("li")

function inputLength() {
    return input.value.length;
}

function createDelete(){
    // Create a delete button and configure it:
    var btnDelete = document.createElement("button");
    btnDelete.classList.add("delete");
    btnDelete.textContent = "Delete";
    return btnDelete; // <-- send the new element back to the function caller
}

function createListElement() {
    let li = document.createElement("li")
    li.appendChild(document.createTextNode(input.value))
    ul.appendChild(li)
    input.value = ""

    // Append the button to the list item
    // The createDelete() function will be called first
    // and its return value (the new button) is what will 
    // be appended.
    li.appendChild(createDelete());
}

// Create a delete button for each <li> already in the HTML file
li.forEach(function(item){
    // The createDelete() function will be called first
    // and its return value (the new button) is what will 
    // be appended.
    item.appendChild(createDelete());
});

function addListAfterClick() {
    if(inputLength() > 0) {
        createListElement()
    }
}

function addListAfterKeypress(event) {
    if(inputLength() > 0 && event.keyCode === 13) {
        createListElement()
    }
}

button.addEventListener("click", addListAfterClick)

input.addEventListener("keypress", addListAfterKeypress)


function toggleClassDoneOnAndOff(event) {
    if (event.target.tagName === "LI") {
        event.target.classList.toggle("done");
    }
}

ul.addEventListener("click", toggleClassDoneOnAndOff);

function deleteAfterClick(event) {
    // Determine if it was a delete button that was clicked
    if(event.target.classList.contains("delete")){
      // Remove the closest li ancestor to the clicked element
      event.target.closest("li").remove();
    }
  
  }

// Handle all the clicks that originate from within the <ul> at
// the <ul> level when they bubble up to it instead of setting each
// button within the <ul> up with its own click event handler.
ul.addEventListener("click", deleteAfterClick);
.done {
    text-decoration: line-through;
}
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <input id="userinput" type="text" placeholder="Add items">
    <button id="add">Add</button>
    <ul id="ul">
        <li>Notebook</li>
        <li>Jello</li>
        <li>Spinach</li>
        <li>Rice</li>
        <li>Birthday Cake</li>
        <li>Candles</li>
    </ul>
    <script type="text/javascript" src="script.js"></script>
</body>

你可以创建这个函数,

 function createBtnDelete(btn) {
        const btnDelete = document.createElement("button");
        btnDelete.classList.add("delete");
        btnDelete.textContent = "Delete";
        btn.appendChild(btnDelete);
    }

并使用 li.forEach((btn) => createBtnDelete(btn)); 发送每个 li 项目作为 arg 然后,当您创建一个新按钮时,您可以调用相同的函数发送您创建的 li 作为 arg,如下所示

function createListElement() {

        let li = document.createElement("li")
        li.appendChild(document.createTextNode(input.value))
        ul.appendChild(li)
        input.value = ""

      
        // Create a delete button and configure it:
        createBtnDelete(li);
       
    }