在indexedDb中,我的addEventListener得到了following error:
like-unlike-button.js:46 Uncaught (in promise) TypeError: Cannot read property 'addEventListener' of null
at Object._renderLiked (like-unlike-button.js:46)
at Object._renderButton (like-unlike-button.js:21)
at async Object.init (like-unlike-button.js:13)
我认为我在deleteRestaurant()
中将错误的参数传递给了_renderLiked()
。
源代码:
like-unlike-button.js
import FavoriteResto from '../data/favorite-resto'
import { createLikeButton, createUnlikeButton } from '../templates/template-creator'
const LikeButtonInitiator = {
async init ({ likeButtonContainer, url, resto }) {
this._likeButtonContainer = likeButtonContainer
this._resto = resto
this._url = url
await this._renderButton()
},
async _renderButton () {
const { id } = this._resto
const { url } = this._url
if (await this._isRestaurantExist(id)) {
this._renderLiked(id)
} else {
this._renderLike()
}
},
async _isRestaurantExist (id) {
const resto = await FavoriteResto.getRestaurant(id)
return !!resto
},
_renderLike () {
this._likeButtonContainer.innerHTML = createLikeButton()
const likeButton = document.querySelector('#like-button')
likeButton.addEventListener('click', async () => {
await FavoriteResto.putRestaurant(this._resto.ikd)
this._renderButton()
})
},
_renderLiked () {
this._likeButtonContainer.innerHTML = createUnlikeButton()
const likeButton = document.getElementById('like-button')
likeButton.addEventListener('click', async () => {
await FavoriteResto.deleteRestaurant(this._url.id)
this._renderButton()
})
}
}
export default LikeButtonInitiator
detail.js
import UrlParser from '../url/url-parser'
import RestaurantSource from '../data/restaurant-source'
import { createRestaurantDetail } from '../templates/template-creator'
import LikeButtonInitiator from '../tools/like-unlike-button'
import dateNow from '../tools/dateNow'
const Detail = {
async render () {
return `
<h2 class="title">Detail Restaurant</h2>
<div id="detail"></div>
<div id="likeButtonContainer"></div>
`
},
async afterRender () {
const url = UrlParser.parseActiveUrlWithoutCombiner()
const resto = await RestaurantSource.DetailResto(url.id)
const restoDetail = document.querySelector('#detail')
const restaurants = createRestaurantDetail(resto.restaurant)
restoDetail.innerHTML = restaurants
console.log(resto.restaurant)
LikeButtonInitiator.init({
likeButtonContainer: document.querySelector('#likeButtonContainer'),
url,
resto: {
id: url.id,
pictureId: resto.restaurant.pictureId,
name: resto.restaurant.name,
description: resto.restaurant.description,
rating: resto.restaurant.rating,
city: resto.restaurant.city
}
})
const submitButton = document.querySelector('#input-submit')
submitButton.addEventListener('click', () => {
const inputName = document.querySelector('#input-name').value
const inputReview = document.querySelector('#input-review').value
const inputText = {
id: url.id,
name: inputName,
review: inputReview,
date: dateNow
}
RestaurantSource.PostReview(inputText)
const updateUi = document.querySelector('.detail-review-grid')
updateUi.innerHTML += `
<div class="detail-review-card">
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
<div class="detail-review-text">
<p class="detail-review-name">${inputText.name}</p>
<p class="detail-review-date">${inputText.date}</p>
<p class="detail-review-reviewer">${inputText.review}</p>
</div>
</div>
`
document.querySelector('#input-name').value = ''
document.querySelector('#input-review').value = ''
})
}
}
export default Detail
favorite-resto.js
import { openDB } from 'idb'
import CONFIG from './config'
const { DATABASE_NAME, DATABASE_VERSION, OBJECT_STORE_NAME } = CONFIG
const dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {
upgrade (database) {
database.createObjectStore(OBJECT_STORE_NAME, { keyPath: 'id', autoIncrement: true })
}
})
const FavoriteResto = {
async getRestaurant (id) {
return (await dbPromise).get(OBJECT_STORE_NAME, id)
},
async getAllRestaurant () {
return (await dbPromise).getAll(OBJECT_STORE_NAME)
},
async putRestaurant (resto) {
return (await dbPromise).put(OBJECT_STORE_NAME, resto)
},
async deleteRestaurant (id) {
return (await dbPromise).delete(OBJECT_STORE_NAME, id)
}
}
export default FavoriteResto
答案 0 :(得分:0)
此template-creator.js 从'../data/config'导入CONFIG
const createRestaurantList = (restaurant) => `
<div class="cards-item">
<div class="card">
<div class="card-image">
<span class="label-rating fa fa-star"> ${restaurant.rating}</span>
<span class="label-city fa fa-building-o"> ${restaurant.city}</span>
<a href="${`/#/detail/${restaurant.id}`}" class="card-title">
<img class="imagecard" alt="picture of restaurant" src="${CONFIG.BASE_URL_PHOTO}/${restaurant.pictureId}">
</a>
</div>
<div class="card-content">
<a href="${`/#/detail/${restaurant.id}`}" class="card-title">${restaurant.name}</a>
<p class="card-text" maxlength="100">${restaurant.description}</p>
</div>
</div>
</div>
`
const createRestaurantDetail = (restaurant) => `
<div class="detail-container">
<div class="detail-card">
<img class="detail-image" alt="picture of restaurant" src="${CONFIG.BASE_URL_PHOTO}/${restaurant.pictureId}">
<div class="detail-text">
<h2 class="detail-title">${restaurant.name}</h2>
<p><i class="fa fa-star" aria-hidden="true"></i> ${restaurant.rating}</p>
<p><i class="fa fa-map-marker" aria-hidden="true"></i> ${restaurant.address}, ${restaurant.city}</p>
<p><i class="fa fa-cutlery" aria-hidden="true"></i> ${restaurant.categories
.map((category) => `
${category.name}
`
).join('')}
</p>
<p>${restaurant.description}</p>
</div>
</div>
</div>
<div class="detail-menus-container">
<h2 class="detail-container-title">Menu</h2>
<div class="detail-menus-flex">
<ul class="detail-menus-foods">
<h3><i class="fa fa-spoon" aria-hidden="true"></i> Foods</h3>${restaurant.menus.foods
.map((food) => `
<li class="detail-menus-items">${food.name}</li>
`
).join('')}
</ul>
<ul class="detail-menus-drinks">
<h3><i class="fa fa-glass" aria-hidden="true"></i> Drinks</h3>${restaurant.menus.drinks
.map((drink) => `
<li class="detail-menus-items">${drink.name}</li>
`
).join('')}
</ul>
</div>
</div>
<div class="detail-review-container">
<h2 class="detail-container-title">Consumer Reviews</h2>
<div class="detail-review-grid">
${restaurant.consumerReviews
.map((reviews) => `
<div class="detail-review-card">
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
<div class="detail-review-text">
<p class="detail-review-name">${reviews.name}</p>
<p class="detail-review-date">${reviews.date}</p>
<p class="detail-review-reviewer">${reviews.review}</p>
</div>
</div>
`
).join('')}
</div>
</div>
<div class="input-review-container">
<h2 class="input-review-title">Review this restaurant</h2>
<input id="input-name" value="" aria-label="Text name here..." type="text" placeholder="Enter your Name...">
<textarea id="input-review" value="" aria-label="Text review here..." type="text" placeholder="This Resto is awesome..."></textarea>
<button id="input-submit" aria-label="submit">Submit Review</button>
</div>
`
const createLikeButton = () => `
<button aria-label="Like restaurant" id="like-button" class="like-button">
<i class="fa fa-heart-o" aria-hidden="true"></i>
</button>
`
const createUnlikeButton = () => `
<button aria-label="unlike restaurant" id="like-Button" class="like-button">
<i class="fa fa-heart" aria-hidden="true"></i>
</button>
`
export {
createRestaurantList,
createRestaurantDetail,
createLikeButton,
createUnlikeButton
}