JS 库项目的类型错误和 DOM 遍历问题

问题描述 投票:0回答:1

该项目是使用 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
行上产生类型错误。 删除功能根本没有达到其目的。在过去的三天里,我尝试使用我所学到的方法来解决问题,但没有任何效果。如果信息丢失或格式不正确,请提前抱歉。

javascript dom project
1个回答
0
投票

问题是书名不在按钮的

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>

© www.soinside.com 2019 - 2024. All rights reserved.