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

Vanilla JS图书库应用删除按钮失效问题排查及CSS优化建议

图书库应用问题修复与CSS优化建议

我开发了一个基础的Vanilla JS图书库应用,通过提交按钮将新书添加至网格布局和myLibrary数组中,每个图书项的删除按钮通过data-index属性存储对应索引,但删除按钮无响应。以下是问题修复方案和CSS优化建议:


一、删除按钮无响应问题修复

核心问题分析

  1. 添加图书时未传入正确索引:调用addBookToGrid时未传递index参数,导致删除按钮的data-index值为undefined,无法触发正确的删除逻辑。
  2. 渲染函数未清空容器:删除图书后直接调用render()会重复添加所有图书,导致页面出现重复项且索引混乱。
  3. Book构造函数逻辑错误:info方法中的三元运算符未加括号,优先级问题导致判断失效。

修复后的完整JS代码

const myLibrary = [];

function Book(title, author, pages, read) {
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.read = read;
    this.info = function () {
        // 修复三元运算符优先级问题
        return title + " by " + author + ", " + pages + " pages, " + (read ? "read" : "not read yet");
    }
}

function openPopup() {
    const window = document.getElementById("popup-window");
    window.classList.toggle("hidden");
}

const popupBtn = document.getElementById("open-popup");
popupBtn.addEventListener("click", openPopup);

const submitBtn = document.getElementById("submit-btn");
const bookContainer = document.getElementById("book-container");

function addBookToGrid(book, index) {
    const newBook = document.createElement("div");
    newBook.classList.add("book-template");
    newBook.innerHTML = `<div class="bookProperties">
            <h3>Title: ${book.title}</h3>
            <p>Author: ${book.author}</p>
            <p>Pages: ${book.pages}</p>
            <p>Read?: ${book.read}</p>
            <button type="button" class="remove-button" data-index="${index}"> REMOVE </button>
        </div>`;

    bookContainer.appendChild(newBook);
    const removeButton = newBook.querySelector(".remove-button");
    removeButton.addEventListener("click", deleteBook);
}

function render() {
    // 清空容器避免重复渲染
    bookContainer.innerHTML = "";
    for (let i = 0; i < myLibrary.length; i++) {
        addBookToGrid(myLibrary[i], i);
    }
}

function deleteBook(e) {
    const index = parseInt(e.target.dataset.index);
    myLibrary.splice(index, 1);
    render();
}

function addBookToList() {
    const book = {
        title: document.getElementById("name").value,
        author: document.getElementById("author").value,
        pages: document.getElementById("pages").value,
        read: document.querySelector('input[name="read"]:checked').value
    };
    myLibrary.push(book);
    // 清空表单
    document.getElementById("name").value = "";
    document.getElementById("author").value = "";
    document.getElementById("pages").value = "";
    document.querySelector('input[name="read"]:checked').checked = false;
    // 重新渲染所有图书
    render();
}

submitBtn.addEventListener("click", addBookToList);
submitBtn.addEventListener("click", openPopup);

关键修复点说明

  • 绑定正确索引:添加图书后调用render(),确保所有图书的索引与数组位置一致。
  • 清空容器再渲染:每次render前清空bookContainer,避免重复元素。
  • 修复逻辑判断:给三元运算符添加括号,确保read状态判断正确。
  • 索引类型转换:将data-index转为数字,避免splice方法出错。

二、CSS优化建议

优化后的完整CSS代码

/* CSS变量统一管理样式参数 */
:root {
    --primary-color: #00796b;
    --primary-dark: #005a4e;
    --light-gray: #f0f0f0;
    --border-color: #ccc;
    --shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    --gap: 15px;
}

html, body {
    height: 100vh;
    margin: 0;
    font-family: Arial, sans-serif;
}

#open-popup {
    width: 8em;
    position: absolute;
    left: 10%;
    transform: translate(-50%, -50%);
    top: 15%;
    height: 6vh;
    font-size: 1.2rem;
    z-index: 10;
}

.header {
    background-color: var(--primary-color);
    color: white;
    padding: 1rem 2rem;
}

/* 添加弹窗遮罩层 */
.popup-window {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
}

.popup-window-inner {
    padding: 35px;
    background-color: var(--light-gray);
    border: 1px solid var(--border-color);
    box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
    font-weight: 600;
    font-size: 1.2rem;
    border-radius: 5px;
    width: 90%;
    max-width: 500px;
}

.radio-container {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--gap);
}

.radio-container div {
    display: flex;
    align-items: center;
    width: auto;
}

.hidden {
    display: none;
}

fieldset {
    border: 0;
    padding: 0;
    margin: 0;
}

.labelinput {
    display: flex;
    justify-content: flex-end;
    gap: var(--gap);
    align-items: center;
}

input {
    background-color: rgba(12, 74, 74, 0.08);
    accent-color: var(--primary-color);
    font-weight: 700;
    height: 25px;
}

input[type="radio"] {
    width: auto;
    height: 1em;
    border: 0;
}

.form {
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--gap);
    background-color: var(--light-gray);
    padding: 20px;
    border-radius: 5px;
}

input[type="text"],
input[type="number"] {
    border: 1px solid var(--border-color);
    border-radius: 5px;
    padding: 0.5rem;
    flex: 1;
}

input[type="radio"] {
    margin-right: 5px;
}

.submit-btn {
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    font-size: 1.2rem;
    margin-top: var(--gap);
}

legend {
    margin: 25px auto;
    font-weight: 800;
    font-size: 1.5rem;
    color: #000;
}

.book-container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    grid-gap: 20px;
    width: 90%;
    max-width: 1200px;
    margin: 0 auto;
}

.book-list {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 2rem;
}

.book-template {
    border: 1px solid var(--border-color);
    min-height: 250px;
    padding: 20px;
    box-shadow: var(--shadow);
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: 5px;
    background-color: white;
}

.bookProperties {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 15px;
    width: 100%;
}

button {
    background-color: var(--primary-color);
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

button:hover {
    background-color: var(--primary-dark);
}

优化点说明

  1. 统一样式管理:使用CSS变量定义颜色、间距等参数,便于全局修改和维护。
  2. 响应式优化:
    • 弹窗添加半透明遮罩层,提升交互体验;限制弹窗最大宽度,适配小屏幕。
    • 图书网格使用百分比宽度+max-width,适配不同设备屏幕。
    • 字体大小使用rem单位,适配系统字体设置。
  3. 视觉体验提升:
    • 给header添加内边距,避免文字贴边。
    • 表单输入框添加内边距,优化输入体验。
    • 图书卡片添加白色背景,增强内容对比度。
  4. 细节修正:
    • 统一类名:将CSS中的book-properties改为bookProperties,与HTML保持一致。
    • 取消radio容器固定宽度,自适应内容。
    • 提升添加按钮z-index,避免被遮挡。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:32:33