函数可嵌套吗?图书馆项目changeColor失效及状态切换问题求助
问题分析与修复方案
核心问题列表
changeColor函数未执行:你定义了该函数但从未调用,导致颜色无变化。- DOM选择错误:
document.querySelector(".card")仅会选中页面第一个.card元素,无法定位到点击按钮对应的目标卡片。 - 循环语法错误:
for (let i = 0; i < length.myLibrary; i++)写法错误,正确应为myLibrary.length。 - 冗余代码:
readStatus里的Book.prototype = Object.create(Book.prototype);和const toggleBook = new Book();完全没必要,直接修改数组内对象的属性即可。 - 颜色设置时机错误:点击修改状态后调用
displayOnPage()会重建所有卡片,此时在readStatus里设置颜色会被渲染覆盖,应该在渲染卡片时就根据read状态设置背景色。
修复后的完整代码
JavaScript部分
let myLibrary = []; function Book(title, author, pages, read) { this.title = title; this.author = author; this.pages = pages; this.read = read; } function addBookToLibrary(title, author, pages, read) { let book = new Book(title, author, pages, read); myLibrary.push(book); displayOnPage(); } function displayOnPage() { const books = document.querySelector(".books"); const removeDivs = document.querySelectorAll(".card"); for (let i = 0; i < removeDivs.length; i++) { removeDivs[i].remove(); } let index = 0; myLibrary.forEach((book) => { let card = document.createElement("div"); card.classList.add("card"); // 渲染时直接根据read状态设置背景色 card.style.backgroundColor = book.read === "yes" ? "green" : "red"; books.appendChild(card); for (let key in book) { let para = document.createElement("p"); para.textContent = `${key}: ${book[key]}`; card.appendChild(para); } let read_button = document.createElement("button"); read_button.classList.add("read_button"); read_button.textContent = "Toggle Read Status"; read_button.dataset.linkedArray = index; card.appendChild(read_button); read_button.addEventListener("click", readStatus); let delete_button = document.createElement("button"); delete_button.classList.add("delete_button"); delete_button.textContent = "Remove"; delete_button.dataset.linkedArray = index; card.appendChild(delete_button); delete_button.addEventListener("click", removeFromLibrary); function removeFromLibrary() { let retrieveBookToRemove = delete_button.dataset.linkedArray; myLibrary.splice(parseInt(retrieveBookToRemove), 1); displayOnPage(); } function readStatus() { let bookIndex = parseInt(this.dataset.linkedArray); // 直接切换read状态,去掉冗余代码 myLibrary[bookIndex].read = myLibrary[bookIndex].read === "yes" ? "no" : "yes"; // 重新渲染页面,自动更新颜色 displayOnPage(); } index++; }); } let add_book = document.querySelector(".add-book"); add_book.addEventListener("click", popUpForm); function popUpForm() { document.getElementById("data-form").style.display = "block"; } function closeForm() { document.getElementById("data-form").style.display = "none"; } let close_form_button = document.querySelector("#close-form"); close_form_button.addEventListener("click", closeForm); function intakeFormData() { let title = document.getElementById("title").value; let author = document.getElementById("author").value; let pages = document.getElementById("pages").value; let read = document.getElementById("read").value; if (title === "" || author === "" || pages === "" || read === "") { return; } addBookToLibrary(title, author, pages, read); document.getElementById("data-form").reset(); closeForm(); // 提交后关闭表单 } let submit_form = document.querySelector("#submit-form"); submit_form.addEventListener("click", function (event) { event.preventDefault(); intakeFormData(); });
CSS部分(保持原代码)
* { margin: 0; padding: 0; background-color: rgb(245, 227, 205); } .books { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; text-align: center; margin: 20px; gap: 10px; } .card { border: 1px solid black; border-radius: 15px; padding: 10px; } .forms { display: flex; flex-direction: column; align-items: center; } form { margin-top: 20px; } select, input[type="text"], input[type="number"] { width: 100%; box-sizing: border-box; } .buttons-container { display: flex; margin-top: 10px; } .buttons-container button { width: 100%; margin: 2px; } .add-book { margin-top: 20px; } #data-form { display: none; } .read_button { margin-right: 10px; }
HTML部分(保持原代码)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="style.css" /> <title>Document</title> </head> <body> <div class="container"> <div class="forms"> <button class="add-book">Add Book To Library</button> <div class="pop-up"> <form id="data-form"> <div class="form-container"> <label for="title">Title</label> <input type="text" name="title" id="title" /> </div> <div class="form-container"> <label for="author">Author</label> <input type="text" name="author" id="author" /> </div> <div class="form-container"> <label for="pages">Pages</label> <input type="number" name="pages" id="pages" /> </div> <div class="form-container"> <label for="read">Read</label> <select name="read" id="read"> <option value="yes">Yes</option> <option value="no">No</option> </select> </div> <div class="buttons-container"> <button type="submit" id="submit-form">Submit Form</button> <button type="button" id="close-form">Close Form</button> </div> </form> </div> </div> <div class="books"></div> </div> <script src="script.js"></script> </body> </html>
关键修复说明
- 移除冗余代码:删掉
readStatus中不必要的Book原型操作和空实例创建,直接修改数组内对应图书的read属性。 - 渲染时设置颜色:在
displayOnPage创建卡片的同时,根据当前图书的read状态设置背景色,避免点击后设置被渲染覆盖的问题。 - 简化状态切换逻辑:用三元表达式一行完成
read状态切换,代码更简洁。 - 修正索引获取方式:用
this.dataset.linkedArray获取当前按钮对应的图书索引,比直接引用外部变量更可靠。 - 优化用户体验:在
intakeFormData中添加closeForm(),提交表单后自动关闭弹窗。
内容的提问来源于stack exchange,提问作者Jose Velasco
相关产品推荐
相关产品推荐

