You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript动态创建删除按钮与已读状态按钮的实现问题

图书馆应用:实现每行的删除按钮与已读状态切换功能

我正在开发一款图书馆应用,尝试用对象数组动态生成书籍信息行,但现在没法给每行添加能删除整行的按钮,也做不了标记书籍已读的勾选按钮。原本计划把状态按钮作为对象属性存入数组,让每行显示姓名、书名、页数和已读状态。

原HTML代码

<div class = "container">
    <div class = "header">

    </div>

    <div class = "books">
        <div class = "book">
            <form id = "Form" onsubmit = "event.preventDefault();">
                <label for = "fname">First Name:</label>
                <input type = "text" id = "fname" name = "fname">
                <label for = "lname">Last Name:</label>
                <input type = "text" id = "lname" name = "lname">
                <label for = "title">Title:</label>
                <input type = "text" id = "title" name = "title">
                <label for = "pages">Pages:</label>
                <input type = "number" id = "pages" name = "pages">
                <label for = "read">Read</label>
                <input type = "checkbox" id = "read" name = "read" value = "Read">

                <button class = "addBook" onclick = "addBookToLibrary(); clearInput()">Add Book</button>
            </form>
        </div>
    </div>

    <div id = "bookInfo">
        <div id = "firstName"></div>
        <div id = "lastName"></div>
        <div id = "bookTitle"></div>
        <div id = "pageNum"></div>
        <button id = "delete"></button>
    </div>

</div>

原JavaScript代码

let myLibrary = [];
function Book(firstName, lastName, title, pages, read) 
{
    this.firstName = firstName
    this.lastName = lastName
    this.title = title
    this.pages = pages
    this.read = read
}

function addBookToLibrary() 
{
    var firstName = document.getElementById("fname").value;
    var secondName = document.getElementById("lname").value;
    var title = document.getElementById("title").value;
    var pages = document.getElementById("pages").value;
    var read = document.getElementById("read").value;
    const book = new Book(firstName, secondName, title, pages, read);
    myLibrary.push(book);
    console.log(myLibrary);
    displayBooks();
}


function displayBooks()
{
    let name1 = " ";
    let name2 = " ";
    let bookT = " ";
    let numPages = " ";
    
    for (i = 0; i < myLibrary.length; i++)
    {
        name1 += myLibrary[i].firstName + '<br/>';
        document.getElementById("firstName").innerHTML = name1;
        name2 += myLibrary[i].lastName + '<br/>';
        document.getElementById("lastName").innerHTML = name2;
        bookT += myLibrary[i].title + '<br/>';
        document.getElementById("bookTitle").innerHTML = bookT;
        numPages += myLibrary[i].pages + '<br/>';
        document.getElementById("pageNum").innerHTML = numPages;
    }
}

解决方案

原代码的核心问题是把书籍的各个字段拆分渲染,无法为单本书绑定独立的操作按钮。需要重构渲染逻辑,让每本书的信息和操作按钮作为一个整体生成。

修改点说明

  1. 修正addBookToLibrary中已读状态的取值:复选框的value是固定值,应该取checked属性获取布尔值,这样能正确记录书籍是否已读。
  2. 重构displayBooks函数:每次渲染前清空容器,遍历数组为每本书创建独立的行容器,包含信息、已读复选框和删除按钮,并绑定对应事件。
  3. 简化HTML结构:移除bookInfo内的固定子div,改为动态生成内容。

修改后的代码

HTML部分

<div class = "container">
    <div class = "header">

    </div>

    <div class = "books">
        <div class = "book">
            <form id = "Form" onsubmit = "event.preventDefault();">
                <label for = "fname">First Name:</label>
                <input type = "text" id = "fname" name = "fname">
                <label for = "lname">Last Name:</label>
                <input type = "text" id = "lname" name = "lname">
                <label for = "title">Title:</label>
                <input type = "text" id = "title" name = "title">
                <label for = "pages">Pages:</label>
                <input type = "number" id = "pages" name = "pages">
                <label for = "read">Read</label>
                <input type = "checkbox" id = "read" name = "read">

                <button class = "addBook" onclick = "addBookToLibrary(); clearInput()">Add Book</button>
            </form>
        </div>
    </div>

    <!-- 只保留空的容器,动态生成内容 -->
    <div id = "bookInfo"></div>

</div>

JavaScript部分

let myLibrary = [];
function Book(firstName, lastName, title, pages, read) 
{
    this.firstName = firstName
    this.lastName = lastName
    this.title = title
    this.pages = pages
    this.read = read
}

function addBookToLibrary() 
{
    var firstName = document.getElementById("fname").value;
    var secondName = document.getElementById("lname").value;
    var title = document.getElementById("title").value;
    var pages = document.getElementById("pages").value;
    // 修正:取复选框的checked状态,而非固定value
    var read = document.getElementById("read").checked;
    const book = new Book(firstName, secondName, title, pages, read);
    myLibrary.push(book);
    displayBooks();
}

// 新增清空输入框的函数(原代码调用但未定义)
function clearInput() {
    document.getElementById("fname").value = "";
    document.getElementById("lname").value = "";
    document.getElementById("title").value = "";
    document.getElementById("pages").value = "";
    document.getElementById("read").checked = false;
}

function displayBooks()
{
    const bookInfoContainer = document.getElementById("bookInfo");
    // 每次渲染前清空容器,避免重复内容
    bookInfoContainer.innerHTML = "";

    myLibrary.forEach((book, index) => {
        // 创建单本书的行容器
        const bookRow = document.createElement("div");
        bookRow.className = "book-row";
        bookRow.style.display = "flex";
        bookRow.style.gap = "1rem";
        bookRow.style.margin = "0.5rem 0";

        // 添加书籍信息
        bookRow.innerHTML = `
            <span>${book.firstName} ${book.lastName}</span>
            <span>${book.title}</span>
            <span>${book.pages}页</span>
        `;

        // 创建已读复选框
        const readCheckbox = document.createElement("input");
        readCheckbox.type = "checkbox";
        readCheckbox.checked = book.read;
        // 绑定状态切换事件
        readCheckbox.addEventListener("change", () => {
            myLibrary[index].read = readCheckbox.checked;
        });
        bookRow.appendChild(readCheckbox);

        // 创建删除按钮
        const deleteBtn = document.createElement("button");
        deleteBtn.textContent = "删除";
        // 绑定删除事件
        deleteBtn.addEventListener("click", () => {
            myLibrary.splice(index, 1);
            displayBooks(); // 删除后重新渲染
        });
        bookRow.appendChild(deleteBtn);

        // 把行容器加入主容器
        bookInfoContainer.appendChild(bookRow);
    });
}

关键逻辑说明

  • 行级容器:每本书的信息和操作按钮都放在独立的div中,确保操作只对应当前书籍。
  • 已读状态绑定:复选框的checked属性与数组中书籍的read字段同步,修改复选框时直接更新数组数据。
  • 删除操作:通过splice删除数组中对应索引的书籍,然后重新调用displayBooks刷新界面。

内容的提问来源于stack exchange,提问作者silentcoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 12:55:25