为什么我会收到单击任何按钮的警报消息? + 需要提示
Why am I getting the alert message for any buttons clicked? + Hints needed
基本上,我正在尝试添加功能,点击蓝色按钮后,阅读状态将变为 <Yes>
或 <Not>
。在这种意义上的任何线索将不胜感激。其次,我不知道为什么在他们那一刻,单击该按钮时我会收到警报,这本书没有被删除(除非您单击正确的图标)但仍然......我无法弄清楚我们的缺陷按照我的逻辑!!
JS代码:
// Book Class: Represents a Book
class Book {
constructor(title, author, pages, isRead) {
this.title = title;
this.author = author;
this.pages = pages;
this.isRead = isRead;
}
}
// UI Class: Handle UI Tasks
class UI {
static displayBooks() {
const books = Store.getBooks();
books.forEach((book) => UI.addBookToList(book));
}
static addBookToList(book) {
const list = document.querySelector("#book-list");
const row = document.createElement("tr");
row.innerHTML = `
<td>${book.title}</td> </button>
<td>${book.author}</td>
<td>${book.pages}</td>
<td><button class="btn btn-sm btn-primary">${book.isRead}</button></td>
<td><a href="#" class="btn btn-danger btn-sm delete">X</a></td>
`;
list.appendChild(row);
}
static deleteBook(el) {
if (el.classList.contains("delete")) {
el.parentElement.parentElement.remove();
}
}
static showAlert(message, className) {
const div = document.createElement("div");
div.className = `alert alert-${className}`;
div.appendChild(document.createTextNode(message));
const container = document.querySelector(".container");
const form = document.querySelector("#book-form");
container.insertBefore(div, form);
// Vanish in 3 seconds
setTimeout(() => document.querySelector(".alert").remove(), 3000);
}
static clearFields() {
document.querySelector("#title").value = "";
document.querySelector("#author").value = "";
document.querySelector("#pages").value = "";
document.querySelector("#isRead").value = "";
}
}
// Store Class: Handles Storage
class Store {
static getBooks() {
let books;
if (localStorage.getItem("books") === null) {
books = [];
} else {
books = JSON.parse(localStorage.getItem("books"));
}
return books;
}
static addBook(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem("books", JSON.stringify(books));
}
static removeBook(pages) {
const books = Store.getBooks();
books.forEach((book, index) => {
if (book.pages === pages) {
books.splice(index, 1);
}
});
localStorage.setItem("books", JSON.stringify(books));
}
}
// Event: Display Books
document.addEventListener("DOMContentLoaded", UI.displayBooks);
// Event: Add a Book
document.querySelector("#book-form").addEventListener("submit", (e) => {
// Prevent actual submit
e.preventDefault();
// Get form values
const title = document.querySelector("#title").value;
const author = document.querySelector("#author").value;
const pages = document.querySelector("#pages").value;
const isRead = document.querySelector("#isRead").value;
// Validate
if (title === "" || author === "" || pages === "" || isRead === "") {
UI.showAlert("Please fill in all fields", "danger");
} else {
// Instatiate book
const book = new Book(title, author, pages, isRead);
// Add Book to UI
UI.addBookToList(book);
// Add book to store
Store.addBook(book);
// Show success message
UI.showAlert("Book Added", "success");
// Clear fields
UI.clearFields();
}
});
// Event: Remove a Book
document.querySelector("#book-list").addEventListener("click", (e) => {
// Remove book from UI
UI.deleteBook(e.target);
// Remove book from store
Store.removeBook(
e.target.parentElement.previousElementSibling.previousElementSibling
.textContent
);
// Show success message
UI.showAlert("Book Removed", "success");
});
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" />
<title>My BookListApp</title>
<link
rel="stylesheet"
href="https://bootswatch.com/4/yeti/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.15.4/css/all.css"
integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center">
<i class="fas fa-book-open text-primary"></i>My
<span class="text-primary">BookList</span> App
</h1>
<form id="book-form">
<div class="form-group">
<label for="title">Title:</label>
<input type="text" id="title" class="form-control" maxlength="30" />
</div>
<div class="form-group">
<label for="author">Author:</label>
<input type="text" id="author" class="form-control" maxlength="20" />
</div>
<div class="form-group">
<label for="pages">Pages:</label>
<input
type="number"
id="pages"
class="form-control"
min="1"
max="10000"
/>
</div>
<div class="form-group">
<label for="isRead">Read:</label>
<select type="number" id="isRead" class="form-control">
<option value="" selected disabled hidden></option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</div>
<input
type="submit"
value="Add Book"
class="btn btn-primary btn-block"
/>
</form>
<table class="table table-striped mt-5">
<thead>
<tr>
<th>Title:</th>
<th>Author:</th>
<th>Pages:</th>
<th>Read:</th>
<th></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="./src/app.js"></script>
</body>
</html>
谢谢!
这个 onclick 太宽泛了:
document.querySelector("#book-list").addEventListener("click",
每次点击书籍中的任何地方都会触发它 list/table。不只是在按钮上。任何地方。如果你不点击按钮,JS 就会崩溃。如果您点击 Yes/No 按钮,JS 不会中断,但它会 尝试 删除这本书,有点。
损坏 jsfiddle:https://jsfiddle.net/do42Lkqn/
解决方案:明确检查单击了哪个按钮。在点击处理程序中,您可以执行以下操作:
if (!e.target.closest('.delete')) return;
因此,如果您没有单击 .delete
元素,它不会执行任何操作。
基本上,我正在尝试添加功能,点击蓝色按钮后,阅读状态将变为 <Yes>
或 <Not>
。在这种意义上的任何线索将不胜感激。其次,我不知道为什么在他们那一刻,单击该按钮时我会收到警报,这本书没有被删除(除非您单击正确的图标)但仍然......我无法弄清楚我们的缺陷按照我的逻辑!!
JS代码:
// Book Class: Represents a Book
class Book {
constructor(title, author, pages, isRead) {
this.title = title;
this.author = author;
this.pages = pages;
this.isRead = isRead;
}
}
// UI Class: Handle UI Tasks
class UI {
static displayBooks() {
const books = Store.getBooks();
books.forEach((book) => UI.addBookToList(book));
}
static addBookToList(book) {
const list = document.querySelector("#book-list");
const row = document.createElement("tr");
row.innerHTML = `
<td>${book.title}</td> </button>
<td>${book.author}</td>
<td>${book.pages}</td>
<td><button class="btn btn-sm btn-primary">${book.isRead}</button></td>
<td><a href="#" class="btn btn-danger btn-sm delete">X</a></td>
`;
list.appendChild(row);
}
static deleteBook(el) {
if (el.classList.contains("delete")) {
el.parentElement.parentElement.remove();
}
}
static showAlert(message, className) {
const div = document.createElement("div");
div.className = `alert alert-${className}`;
div.appendChild(document.createTextNode(message));
const container = document.querySelector(".container");
const form = document.querySelector("#book-form");
container.insertBefore(div, form);
// Vanish in 3 seconds
setTimeout(() => document.querySelector(".alert").remove(), 3000);
}
static clearFields() {
document.querySelector("#title").value = "";
document.querySelector("#author").value = "";
document.querySelector("#pages").value = "";
document.querySelector("#isRead").value = "";
}
}
// Store Class: Handles Storage
class Store {
static getBooks() {
let books;
if (localStorage.getItem("books") === null) {
books = [];
} else {
books = JSON.parse(localStorage.getItem("books"));
}
return books;
}
static addBook(book) {
const books = Store.getBooks();
books.push(book);
localStorage.setItem("books", JSON.stringify(books));
}
static removeBook(pages) {
const books = Store.getBooks();
books.forEach((book, index) => {
if (book.pages === pages) {
books.splice(index, 1);
}
});
localStorage.setItem("books", JSON.stringify(books));
}
}
// Event: Display Books
document.addEventListener("DOMContentLoaded", UI.displayBooks);
// Event: Add a Book
document.querySelector("#book-form").addEventListener("submit", (e) => {
// Prevent actual submit
e.preventDefault();
// Get form values
const title = document.querySelector("#title").value;
const author = document.querySelector("#author").value;
const pages = document.querySelector("#pages").value;
const isRead = document.querySelector("#isRead").value;
// Validate
if (title === "" || author === "" || pages === "" || isRead === "") {
UI.showAlert("Please fill in all fields", "danger");
} else {
// Instatiate book
const book = new Book(title, author, pages, isRead);
// Add Book to UI
UI.addBookToList(book);
// Add book to store
Store.addBook(book);
// Show success message
UI.showAlert("Book Added", "success");
// Clear fields
UI.clearFields();
}
});
// Event: Remove a Book
document.querySelector("#book-list").addEventListener("click", (e) => {
// Remove book from UI
UI.deleteBook(e.target);
// Remove book from store
Store.removeBook(
e.target.parentElement.previousElementSibling.previousElementSibling
.textContent
);
// Show success message
UI.showAlert("Book Removed", "success");
});
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" />
<title>My BookListApp</title>
<link
rel="stylesheet"
href="https://bootswatch.com/4/yeti/bootstrap.min.css"
/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.15.4/css/all.css"
integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm"
crossorigin="anonymous"
/>
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center">
<i class="fas fa-book-open text-primary"></i>My
<span class="text-primary">BookList</span> App
</h1>
<form id="book-form">
<div class="form-group">
<label for="title">Title:</label>
<input type="text" id="title" class="form-control" maxlength="30" />
</div>
<div class="form-group">
<label for="author">Author:</label>
<input type="text" id="author" class="form-control" maxlength="20" />
</div>
<div class="form-group">
<label for="pages">Pages:</label>
<input
type="number"
id="pages"
class="form-control"
min="1"
max="10000"
/>
</div>
<div class="form-group">
<label for="isRead">Read:</label>
<select type="number" id="isRead" class="form-control">
<option value="" selected disabled hidden></option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</div>
<input
type="submit"
value="Add Book"
class="btn btn-primary btn-block"
/>
</form>
<table class="table table-striped mt-5">
<thead>
<tr>
<th>Title:</th>
<th>Author:</th>
<th>Pages:</th>
<th>Read:</th>
<th></th>
</tr>
</thead>
<tbody id="book-list"></tbody>
</table>
</div>
<script src="./src/app.js"></script>
</body>
</html>
谢谢!
这个 onclick 太宽泛了:
document.querySelector("#book-list").addEventListener("click",
每次点击书籍中的任何地方都会触发它 list/table。不只是在按钮上。任何地方。如果你不点击按钮,JS 就会崩溃。如果您点击 Yes/No 按钮,JS 不会中断,但它会 尝试 删除这本书,有点。
损坏 jsfiddle:https://jsfiddle.net/do42Lkqn/
解决方案:明确检查单击了哪个按钮。在点击处理程序中,您可以执行以下操作:
if (!e.target.closest('.delete')) return;
因此,如果您没有单击 .delete
元素,它不会执行任何操作。