javascript - 更新 CRUD 前端时收到 Javascript 程序的未定义错误
问题描述
我为我的 ruby on rails 后端创建了一个前端 javascript,当我尝试更新书名时收到以下错误:
错误:app.js:65 未捕获类型错误:无法读取 App.handleEditClick 处未定义的属性“renderUpdateForm”(app.js:65)
我从后端 api 接收书名及其作者。
这是代码:
document.addEventListener('DOMContentLoaded', () => {
const app = new App();
app.attachEventListeners();
app.adapter.fetchAuthors().then(app.createAuthors);
app.adapter.fetchBooks().then(app.createBooks);
});
class Book {
constructor(data) {
this.id = data.id;
this.title = data.title;
const author = Author.findById(data.author_id);
this.author = author.name;
Book.all.push(this);
}
update({ title }) {
this.title = title;
}
renderListItem() {
return `
<li>
<h3>${this.title} - ${this.author}
<button data-id=${this.id}>update</button>
<button data-id=${this.id}>delete</button>
</h3>
</li>`;
}
renderUpdateForm() {
return `
<form data-id='${this.id}'>
<label>Title</label>
<p>
<input type="text" value="${this.title}" />
</p>
<button type='submit'>Save Book</button>
</form>
`;
}
static findById(id) {
return this.all.find(book => book.id === id);
}
}
Book.all = [];
class App {
constructor() {
this.adapter = new Adapter();
this.handleEditClick = this.handleEditClick.bind(this);
this.handleEditClick = this.handleDeleteClick.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.createBooks = this.createBooks.bind(this);
this.createAuthors = this.createAuthors.bind(this);
this.addBooks = this.addBooks.bind(this);
}
attachEventListeners() {
$('#books-list').on('click', 'button', this.handleEditClick);
$('#books-list').on('click', 'button', this.handleDeleteClick);
$('#update').on('submit', 'form', this.handleFormSubmit);
}
createBooks(books) {
books.forEach(book => {
new Book(book);
});
console.log(this);
this.addBooks();
}
createAuthors(authors) {
authors.forEach(author => {
new Author(author);
});
console.log(this);
this.addAuthors();
}
addBooks() {
$('#books-list').empty();
Book.all.forEach(book => $('#books-list').append(book.renderListItem()));
}
addAuthors() {
$('#authors-list').empty();
Author.all.forEach(author => $('#authors-list').append(author.renderListItem()));
}
handleFormSubmit(e) {
e.preventDefault();
const id = e.target.dataset.id;
const book = Book.findById(id);
const title = $(e.target)
.find('input')
.val();
const bodyJSON = { title };
this.adapter.updateBook(book.id, bodyJSON).then(updatedBook => {
const book = Book.findById(updatedBook.id);
book.update(updatedBook);
this.addBooks();
});
}
handleEditClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
$('#update').html(book.renderUpdateForm());
}
handleDeleteClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
const title = $(e.target)
.find('input')
.val();
const bodyJSON = { title };
this.adapter.deleteBook(book.id, bodyJSON);
}
}
class Adapter {
constructor() {
this.baseUrl = 'http://localhost:3000/api/v1';
this.headers = {
'Content-Type': 'application/json',
Accept: 'application/json'
};
}
fetchBooks() {
return this.get(`${this.baseUrl}/books`);
}
fetchAuthors() {
return this.get(`${this.baseUrl}/authors`);
}
updateBook(id, body) {
return this.patch(`${this.baseUrl}/books/${id}`, body);
}
deleteBook(id, body) {
return this.delete(`${this.baseUrl}/books/${id}`, body);
}
get(url) {
return fetch(url).then(res => res.json());
}
patch(url, body) {
return fetch(url, {
method: 'PATCH',
headers: this.headers,
body: JSON.stringify(body)
}).then(res => res.json());
}
delete(url, body) {
return fetch(url, {
method: 'DELETE',
headers: this.headers,
body: JSON.stringify(body)
}).then(res => res.json());
}
}
解决方案
const book = Book.findById(id);
返回undefined
。
这意味着没有那个条目id
。e.target.dataset.id
可能具有与预期不同的值(console.log
是您的朋友)。
为了防止这种类型的错误(因此当您使用 invalid/non-existent 时您的应用程序不会中断id
),您可以将下一行包装在一个条件中:
handleEditClick(e) {
const id = e.target.dataset.id;
const book = Book.findById(id);
if (book) {
$('#update').html(book.renderUpdateForm());
}
}
更好的检查是结果是否有一个名为 的函数renderUpdateForm
:
if (book && typeof book.renderUpdateForm === 'function') {
$('#update').html(book.renderUpdateForm())
}
或者如果它是 Book 实例:
if (book instanceof Book) {
$('#update').html(book.renderUpdateForm())
}
推荐阅读
- ffmpeg - 如何使用 FFMPEG 正确裁剪和缩放?
- python - Pandas Timestamp(year=2011, month=8, day=1) 返回一个月的最后一天
- c# - 查找集合中可以被另一个集合的数字整除的所有数字
- scala - 将 ml.feature.LabeledPoint 保存到本地 libsvm 文件
- c++ - c++ eigen 3.5,特征图不使用命名返回值优化?
- javascript - 取一个 div 的最大尺寸并使它们都相同
- java - 如何在应用程序中永久单击按钮?
- doctrine - 学说查询生成器,选择分组依据的最后一条记录,但总是返回第一个
- json - 无法从 Elixir/phoenix 中的 Ecto DB 返回 Repo.All
- chicken-scheme - 如何从鸡计划中调用 C 回调