我当前的 JS 项目遇到了问题。这是一个简单的库,用户可以在其中输入信息并将其吐出到页面上。我有一个添加到每个新 div 的删除按钮,我已将事件侦听器添加到按钮中。当我点击删除时,它会删除第一个 - 但就是这样。如果我想删除不止一本书,它就会停止工作。
我认为我的问题是我如何定位分配给每个 div 的数据集/索引值,但我不确定。我尝试过 for 循环、for each 等,但似乎无法弄清楚。
任何帮助将不胜感激。
const book1 = new Book('inserttitlehere', 'His name?', 63, false)
const book2 = new Book('kill bill', 'author2', 653, false)
const book3 = new Book('oh yeah baby', 'author3', 323, false)
const book4 = new Book('kill me now', 'author4', 132, true)
library.push(book1, book2, book3, book4)
// Book constructor
function Book(title, author, pages, completed) {
this.title = title
this.author = author
this.pages = pages
this.completed = completed
}
const main = document.querySelector('main');
const form = document.querySelector('.form');
//Function to add books to the DOM
function displayBooks() {
let dataIndex = 0;
main.innerHTML = '';
library.forEach(book => {
const bookElement = document.createElement('div')
bookElement.classList.add('book');
bookElement.setAttribute('data-index', dataIndex);
bookElement.innerHTML = `
<h3> ${book.title} </h3>
<p> Author: ${book.author}</p>
<p> Pages: ${book.pages}</p>
Completed: <input type="checkbox"> ${book.completed} <br>
<button class="delete">Delete</button>
`
main.appendChild(bookElement);
dataIndex++;
})
}
displayBooks();
//Add new book to library
function addBookToLibrary(title, author, pages, completed) {
const newBook = new Book(title, author, pages, completed)
library.push(newBook);
}
//Deleting a book from the array
let deleteBtns = document.querySelectorAll('.book .delete');
deleteBtns.forEach(button => {
button.addEventListener('click', () => {
const index = button.parentNode.dataset['data-index'];
deleteBook(index);
})
});
function deleteBook(index) {
library.splice(index, 1);
displayBooks();
}
form.addEventListener('submit', (e) => {
e.preventDefault();
const title = document.querySelector('#title').value;
const author = document.querySelector('#author').value;
const pages = document.querySelector('#pages').value;
addBookToLibrary(title, author, pages, false);
document.forms[0].reset();
})
console.log(library);
console.log(deleteBtns);
!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title>Library</title>
</head>
<body>
<nav>
<h1>Library</h1>
<button class="add-book-btn">NEW BOOK</button>
</nav>
<main></main>
<div class="modal">
<form class="form">
<p class="close"></p>
<h2>Add Book</h2>
<div class="user-input">
<label for="">Title</label><br>
<input type="text" id="title" required>
</div>
<div class="user-input">
<label for="">Author</label><br>
<input type="text" id="author" required>
</div>
<div class="user-input">
<label for="">Pages</label><br>
<input type="number" id="pages" required>
</div>
<div class="user-input">
<label for="">Read?</label>
<input type="checkbox" id="read">
</div>
<button type="submit" id="submit">Submit</button>
</form>
</div>
<script src="script.js"></script>
</body>
</html>
答案 0 :(得分:3)
当您构建这样的应用时,通常最好删除不相关的部分,例如表单及其所有相关功能,以便处理其中的特定部分,例如这些用户交互。
>这是一个缩小版本,采用完全不同的方法,在您创建书籍元素时分别向它们添加事件侦听器。
然后不用担心索引,使用数组方法在库中查找 book 对象。因此,与其在删除元素时重建所有元素,不如简单地同时删除数组中的元素和对象。
它被分解成更小的函数,例如 addBookEvents()
,然后在每个不同的事件处理程序中使用 Array.prototype.find()
或 Array.prototype.findIndex()
来修改库。
您为了更改索引而重建所有元素的方法不是很可扩展或效率不高。为了创建此处使用的库数组,我只使用了您的 library.push(book1,book2...)
,然后运行 console.log(JSON.stringify(library))
并将其粘贴到此代码中以使其在此阶段保持精简。
请注意,我将元素上的 data-index
更改为 data-title
,并假设标题在数组中是唯一的。然后允许搜索数组以找到特定的书对象。在标题重复的情况下,使用独特的图书 id
更可靠
const main = document.getElementById('books-list')
library.forEach(createBookElement)
function handleDeleteClick(event) {
const bookElem = event.target.closest('.book');
const title = bookElem.dataset.title;
bookElem.remove();
removeFromLibrary(title)
console.log(title)
}
function handleCompleteChange(event){
const bookElem = event.target.closest('.book');
const title = bookElem.dataset.title;
const checked = event.target.checked;
toggleLibraryComplete(title, checked)
}
function removeFromLibrary(title) {
const idx = library.findIndex(book => book.title === title);
if (idx > -1) {
library.splice(idx, 1);
console.log('library length =', library.length)
}
}
function toggleLibraryComplete(title, checked){
const book = library.find(book => book.title === title);
book.completed = checked;
console.log(JSON.stringify(book))
}
function addBookEvents(bookElement){
const button = bookElement.querySelector('.delete');
button.addEventListener('click', handleDeleteClick);
const checkbox = bookElement.querySelector('.book-complete');
checkbox.addEventListener('change', handleCompleteChange);
}
function createBookElement(book) {
const bookElement = document.createElement('div')
bookElement.classList.add('book');
bookElement.setAttribute('data-title', book.title);
bookElement.innerHTML = `
<h3> ${book.title} </h3>
<p> Author: ${book.author}</p>
<p> Pages: ${book.pages}</p>
Completed: <input class="book-complete" type="checkbox" ${book.completed && 'checked'}> ${book.completed} <br>
<button class="delete">Delete</button>
`;
// add the event listeners for delete and completed
addBookEvents(bookElement);
main.appendChild(bookElement);
}
//console.log(JSON.stringify(library))
<main id="books-list"></main>
<script>
const library =
[{"title":"inserttitlehere","author":"His name?","pages":63,"completed":true},{"title":"kill bill","author":"author2","pages":653,"completed":false},{"title":"oh yeah baby","author":"author3","pages":323,"completed":false},{"title":"kill me now","author":"author4","pages":132,"completed":true}];
</script>
答案 1 :(得分:0)
试试这个:
var library = []
const book1 = new Book('inserttitlehere', 'His name?', 63, false)
const book2 = new Book('kill bill', 'author2', 653, false)
const book3 = new Book('oh yeah baby', 'author3', 323, false)
const book4 = new Book('kill me now', 'author4', 132, true)
library.push(book1, book2, book3, book4)
// Book constructor
function Book(title, author, pages, completed) {
this.title = title
this.author = author
this.pages = pages
this.completed = completed
}
const main = document.querySelector('main');
const form = document.querySelector('.form');
//Function to add books to the DOM
function displayBooks() {
let dataIndex = 0;
main.innerHTML = '';
library.forEach(book => {
const bookElement = document.createElement('div')
bookElement.classList.add('book');
bookElement.setAttribute('data-index', dataIndex);
bookElement.innerHTML = `
<h3> ${book.title} </h3>
<p> Author: ${book.author}</p>
<p> Pages: ${book.pages}</p>
Completed: <input type="checkbox"> ${book.completed} <br>
<button class="delete">Delete</button>
`
main.appendChild(bookElement);
dataIndex++;
})
}
displayBooks();
//Add new book to library
function addBookToLibrary(title, author, pages, completed) {
const newBook = new Book(title, author, pages, completed)
library.push(newBook);
displayBooks();
}
function addListener() {
//Deleting a book from the array
let deleteBtns = document.querySelectorAll('.book .delete');
deleteBtns.forEach(button => {
button.addEventListener('click', () => {
const index = button.parentNode.dataset['data-index'];
deleteBook(index);
})
});
}
addListener();
function deleteBook(index) {
library.splice(index, 1);
displayBooks();
addListener();
}
form.addEventListener('submit', (e) => {
e.preventDefault();
const title = document.querySelector('#title').value;
const author = document.querySelector('#author').value;
const pages = document.querySelector('#pages').value;
addBookToLibrary(title, author, pages, false);
document.forms[0].reset();
})
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title>Library</title>
</head>
<body>
<nav>
<h1>Library</h1>
<button class="add-book-btn">NEW BOOK</button>
</nav>
<main></main>
<div class="modal">
<form class="form">
<p class="close"></p>
<h2>Add Book</h2>
<div class="user-input">
<label for="">Title</label><br>
<input type="text" id="title" required>
</div>
<div class="user-input">
<label for="">Author</label><br>
<input type="text" id="author" required>
</div>
<div class="user-input">
<label for="">Pages</label><br>
<input type="number" id="pages" required>
</div>
<div class="user-input">
<label for="">Read?</label>
<input type="checkbox" id="read">
</div>
<button type="submit" id="submit">Submit</button>
</form>
</div>
<script src="script.js"></script>
</body>
</html>
首先,library
没有定义,所以我在顶部添加了一个数组 library
。然后,我解决了这个问题。
问题是每次删除一本书时,deleteBtn
和按钮事件侦听器都会被更改,因为它们引用的按钮被删除。所以,每次删除一本书时,只需重新初始化它们。我通过将它包装在一个函数中并在每次需要时调用它来做到这一点。
请注意,我还在 displayBooks
下添加了额外的 addBookToLibrary
行,以确保在添加图书时“刷新”页面。