该项目是使用 vanilla JS 和 HTML 创建一个库。我已经基本上完成了整个项目,除了两个功能无法工作。 分别是删除书籍和更改阅读状态,以下是它们的代码片段:
const removeBook = (e) => {
const title = e.currentTarget.innerHTML.replaceAll(
'"',
'',
'Title: ')
library.removeBook(title)
updateLibContainer()
console.log('remove');
}
const toggleRead = (e) => {
const title = e.currentTarget.innerHTML.replaceAll(
'"',
'',
'Title: ')
const book = library.getTitle(title)
book.isRead = !book.isRead
console.log('read');
updateLibContainer()
}
这是 JS 的完整写法:
// Selectors for pop up and closing pop up when x is pressed
const popUp = document.querySelector('.pop-up');
const closePopUp = document.getElementsByTagName('span')[0];
closePopUp.addEventListener('click', () => popUp.style.display = 'none')
const newBookBtn = document.querySelector('.newbtn');
newBookBtn.addEventListener('click', () => popUp.style.display = 'block')
// Constructor for books
class Book {
constructor(
title = 'Unkown',
author = 'Unkown',
pages = 0,
isRead = false
) {
this.title = title
this.author = author
this.pages = pages
this.isRead = isRead
}
}
// Constructor for Library
class Library {
constructor() {
this.books = []
}
addBook(newBook) {
this.books.push(newBook)
}
removeBook(title) {
this.books = this.books.filter((book) => book.title !== title)
}
getTitle(title) {
return this.books.find(book => book.title === title)
}
isInLibrary(title) {
return this.books.some(book => book.title === title)
}
}
const library = new Library()
// Additional UI declarations
const LibContainer = document.getElementById('lib-container')
const addBookForm = document.getElementById('add-form')
// Handling and creating book from form input data
const bookFromInput = () => {
const title = document.getElementById('title').value
const author = document.getElementById('author').value
const pages = document.getElementById('pages').value
const isRead = document.getElementById('is-read').checked
return new Book(title, author, pages, isRead)
}
// Function when form is submitted to create new book from input, check if it exists
// and close form
const addNewBook = (e) => {
e.preventDefault()
const newBook = bookFromInput()
if (library.isInLibrary(newBook.title)) {
alert('Book already exists')
} else {
library.addBook(newBook)
exitForm()
updateLibContainer()
}
}
const exitForm = () => {
addBookForm.reset()
popUp.style.display = 'none'
}
const resetLibContainer = () => {
LibContainer.innerHTML = ''
console.log('reset Container');
}
const updateLibContainer = () => {
resetLibContainer()
for (let book of library.books) {
createBookCard(book)
}
console.log('updateContainer');
}
// Creating book card
const createBookCard = (book) => {
const bookCard = document.createElement('div')
const title = document.createElement('p')
const author = document.createElement('p')
const pages = document.createElement('p')
const changeReadStatus = document.createElement('button')
const removeBookBttn = document.createElement('button')
bookCard.classList.add('book-card')
changeReadStatus.classList.add('change-read-status')
changeReadStatus.onclick = toggleRead
removeBookBttn.classList.add('remove-book')
removeBookBttn.onclick = removeBook
title.textContent = `Title: ${book.title}`
author.textContent = `Author: ${book.author}`
pages.textContent = `Pages: ${book.pages}`
removeBookBttn.textContent = 'Remove'
if (book.isRead) {
changeReadStatus.textContent = 'Read'
changeReadStatus.style.backgroundColor = '#68f364'
} else {
changeReadStatus.textContent = 'Not read'
changeReadStatus.style.backgroundColor = '#d16767'
}
bookCard.appendChild(title)
bookCard.appendChild(author)
bookCard.appendChild(pages)
bookCard.appendChild(changeReadStatus)
bookCard.appendChild(removeBookBttn)
LibContainer.appendChild(bookCard)
}
const removeBook = (e) => {
const title = e.currentTarget.innerHTML.replaceAll(
'"',
'',
'Title: ')
library.removeBook(title)
updateLibContainer()
console.log('remove');
}
const toggleRead = (e) => {
const title = e.currentTarget.innerHTML.replaceAll(
'"',
'',
'Title: ')
const book = library.getTitle(title)
book.isRead = !book.isRead
console.log('read');
updateLibContainer()
}
addBookForm.onsubmit = addNewBook
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<h1>The Library</h1>
</div>
<div class="newbtn-container">
<button class="newbtn">+ New Book</button>
</div>
<div class="pop-up">
<form class="form" action id="add-form">
<span>x</span>
<legend>New book</legend>
<input type="text" id="title" class="form" placeholder="Title">
<input type="text" id="author" class="form" placeholder="Author">
<input type="text" id="pages" class="form" placeholder="Pages">
<div class="checkbox">
<label>Read: </label>
<input type="checkbox" class="form" id="is-read">
</div>
<button class="form" id="submit">Add</button>
</form>
</div>
<div id="lib-container">
<div class="book-card">
<p>Title: 22</p>
<p>Author: 22</p>
<p>Pages: 22</p>
<button class="change-read-status" style="background-color: rgb(209, 103, 103);">Not read</button>
<button class="remove-book">Remove</button>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
如果用户要输入一本书,上面的 HTML 代码中的图书卡只是一个示例占位符。
现在确切的问题是上述两个功能根本不起作用。切换读取功能会在
book.isRead = !book.isRead
行上产生类型错误。
删除功能根本没有达到其目的。在过去的三天里,我尝试使用我所学到的方法来解决问题,但没有任何效果。如果信息丢失或格式不正确,请提前抱歉。
问题是书名不在按钮的
innerHTML
中。它位于 title
<p>
元素中。因此,您需要找到与单击的按钮关联的标题元素。
我建议给该段落上课:
const title = document.createElement('p');
title.classList.add("title");
然后你可以找到包含该按钮的div并导航到相应的标题元素。
无需从标题中删除
"
,您在创建元素时从未添加过它们。您只需删除开头的Title:
即可。
const title = e.currentTarget.closest(".book-card").querySelector(".title").innerText.replace("Title: ");
完整代码
// Selectors for pop up and closing pop up when x is pressed
const popUp = document.querySelector('.pop-up');
const closePopUp = document.getElementsByTagName('span')[0];
closePopUp.addEventListener('click', () => popUp.style.display = 'none')
const newBookBtn = document.querySelector('.newbtn');
newBookBtn.addEventListener('click', () => popUp.style.display = 'block')
// Constructor for books
class Book {
constructor(
title = 'Unkown',
author = 'Unkown',
pages = 0,
isRead = false
) {
this.title = title
this.author = author
this.pages = pages
this.isRead = isRead
}
}
// Constructor for Library
class Library {
constructor() {
this.books = []
}
addBook(newBook) {
this.books.push(newBook)
}
removeBook(title) {
this.books = this.books.filter((book) => book.title !== title)
}
getTitle(title) {
return this.books.find(book => book.title === title)
}
isInLibrary(title) {
return this.books.some(book => book.title === title)
}
}
const library = new Library()
// Additional UI declarations
const LibContainer = document.getElementById('lib-container')
const addBookForm = document.getElementById('add-form')
// Handling and creating book from form input data
const bookFromInput = () => {
const title = document.getElementById('title').value
const author = document.getElementById('author').value
const pages = document.getElementById('pages').value
const isRead = document.getElementById('is-read').checked
return new Book(title, author, pages, isRead)
}
// Function when form is submitted to create new book from input, check if it exists
// and close form
const addNewBook = (e) => {
e.preventDefault()
const newBook = bookFromInput()
if (library.isInLibrary(newBook.title)) {
alert('Book already exists')
} else {
library.addBook(newBook)
exitForm()
updateLibContainer()
}
}
const exitForm = () => {
addBookForm.reset()
popUp.style.display = 'none'
}
const resetLibContainer = () => {
LibContainer.innerHTML = ''
console.log('reset Container');
}
const updateLibContainer = () => {
resetLibContainer()
for (let book of library.books) {
createBookCard(book)
}
console.log('updateContainer');
}
// Creating book card
const createBookCard = (book) => {
const bookCard = document.createElement('div')
const title = document.createElement('p')
title.classList.add("title")
const author = document.createElement('p')
const pages = document.createElement('p')
const changeReadStatus = document.createElement('button')
const removeBookBttn = document.createElement('button')
bookCard.classList.add('book-card')
changeReadStatus.classList.add('change-read-status')
changeReadStatus.onclick = toggleRead
removeBookBttn.classList.add('remove-book')
removeBookBttn.onclick = removeBook
title.textContent = `Title: ${book.title}`
author.textContent = `Author: ${book.author}`
pages.textContent = `Pages: ${book.pages}`
removeBookBttn.textContent = 'Remove'
if (book.isRead) {
changeReadStatus.textContent = 'Read'
changeReadStatus.style.backgroundColor = '#68f364'
} else {
changeReadStatus.textContent = 'Not read'
changeReadStatus.style.backgroundColor = '#d16767'
}
bookCard.appendChild(title)
bookCard.appendChild(author)
bookCard.appendChild(pages)
bookCard.appendChild(changeReadStatus)
bookCard.appendChild(removeBookBttn)
LibContainer.appendChild(bookCard)
}
const removeBook = (e) => {
const title = e.currentTarget.closest(".book-card").querySelector(".title").innerText.replace('Title: ', '')
library.removeBook(title)
updateLibContainer()
console.log('remove');
}
const toggleRead = (e) => {
const title = e.currentTarget.closest(".book-card").querySelector(".title").innerText.replace('Title: ', '')
const book = library.getTitle(title)
book.isRead = !book.isRead
console.log('read');
updateLibContainer()
}
addBookForm.onsubmit = addNewBook
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Library</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<h1>The Library</h1>
</div>
<div class="newbtn-container">
<button class="newbtn">+ New Book</button>
</div>
<div class="pop-up">
<form class="form" action id="add-form">
<span>x</span>
<legend>New book</legend>
<input type="text" id="title" class="form" placeholder="Title">
<input type="text" id="author" class="form" placeholder="Author">
<input type="text" id="pages" class="form" placeholder="Pages">
<div class="checkbox">
<label>Read: </label>
<input type="checkbox" class="form" id="is-read">
</div>
<button class="form" id="submit">Add</button>
</form>
</div>
<div id="lib-container">
<div class="book-card">
<p>Title: 22</p>
<p>Author: 22</p>
<p>Pages: 22</p>
<button class="change-read-status" style="background-color: rgb(209, 103, 103);">Not read</button>
<button class="remove-book">Remove</button>
</div>
</div>
</body>
<script src="script.js"></script>
</html>