未捕获的类型错误:无法读取 null Javascript 的属性“classList”
2021-07-09
162
我有一个对象列表或数组,我通过模板将其传递给 HTML 元素。我有一个 removeItem 函数。它正在删除项目。但在最后一项上,它不会隐藏它。我试图在菜单中没有项目时隐藏菜单。但在最后一项上,它卡住了,没有做任何进一步的事情。模板导致了所有问题。除了模板隐藏之外,其他所有项目都是如此。但事实并非如此。我的 shoppingCart.js 将 cartRemove.classList.add("hide") 设置为 null。.hide 具有 display:none 属性。 错误:
Uncaught TypeError: Cannot read property 'classList' of null
at hideCart (shoppingCart.js:74)
at renderCart (shoppingCart.js:54)
at removeFromCart (shoppingCart.js:68)
at HTMLDocument.<anonymous> (shoppingCart.js:29)
shoppingCart.js
import items from "./items.json";
import { formatCurrency } from "./utils/formatCurrency.js";
const menu = document.querySelector(".menu");
const cart = document.querySelector("#cart");
const cartRemove = document.querySelector("[data-cart-item]");
const storeCartContainer = document.querySelector("[data-cart-container]");
const cartItemTemplate = document.querySelector("#cart-item-template");
const cartQuantity = document.querySelector("[data-cart-quantity]");
const cartTotal = document.querySelector("[data-cart-total]");
const cartHide = document.querySelector(".ahmad");
// total.innerHTML = cartTotal.innerText
let shoppingCart = [];
const IMAGE_URL = "https://dummyimage.com/420x220";
export const toggleCard = cart.addEventListener("click", () => {
menu.classList.toggle("show");
});
export function setupShoppingCart() {
document.addEventListener("click", (e) => {
e.preventDefault()
if (e.target.matches("[data-remove-to-cart-button]")) {
const id = parseInt(e.target.closest("[data-cart-item]").dataset.itemId);
removeFromCart(id);
if (id === null) {
renderCart()
}
}
});
renderCart();
}
export function addToCart(id) {
const existingItem = shoppingCart.find(entry => entry.id === id)
if (existingItem) {
existingItem.quantity++
}
else {
shoppingCart.push({ id: id, quantity: 1 });
}
renderCart();
}
function renderCart() {
if (shoppingCart.length === 0) {
hideCart()
// hideData()
}
else {
showCart()
renderCartItems();
}
}
function removeFromCart(id) {
const existingItem = shoppingCart.find((entry) => entry.id === id);
if (existingItem == null) return;
shoppingCart = shoppingCart.filter((entry) => entry.id !== id);
renderCart();
}
function hideCart() {
cartHide.classList.add("hide");
cartRemove.classList.add("hide"); // This is getting Null
}
function showCart() {
cart.classList.remove("hide")
}
function renderCartItems() {
cartQuantity.innerText = shoppingCart.length;
const totalCents = shoppingCart.reduce((sum, entry) => {
const item = items.find((i) => entry.id === i.id);
return sum + item.priceCents * entry.quantity
},0)
cartTotal.innerText = formatCurrency(totalCents / 100)
storeCartContainer.innerHTML = "";
shoppingCart.forEach((entry) => {
console.log(items, entry);
const item = items.find((i) => entry.id === i.id);
const cartItem = cartItemTemplate.content.cloneNode(true);
const container = cartItem.querySelector("[data-cart-item]");
container.dataset.itemId = item.id;
const name = cartItem.querySelector("[data-cart-name]");
name.innerText = item.name;
if (entry.quantity > 1) {
const quantity = cartItem.querySelector("[data-cart-quantity]");
quantity.innerText = `x${entry.quantity}`;
}
const image = cartItem.querySelector("[data-cart-img]");
image.src = `${IMAGE_URL}/${item.imageColor}/${item.imageColor}`;
const price = cartItem.querySelector("[data-cart-price]");
price.innerText = formatCurrency((item.priceCents * entry.quantity) / 100);
storeCartContainer.appendChild(cartItem);
});
};
store.index
</head>
<body>
<div class="container">
<div class="front-page">
<!-- Section 1 -->
<section class="section-1">
<a href="#" id="cart" class="ahmad">
<i class="fas fa-shopping-cart"></i>
<span data-cart-quantity></span>
</a>
<div>
<div class="menu">
<div data-cart-container> //Template is under this div
<div>
</div>
</div>
<div class="details">
<h5>Total</h5>
<div data-cart-total>
</div> </div>
</div>
</section>
</body>
</head>
<template id="cart-item-template">
<div data-cart-item class="palette">
<button data-remove-to-cart-button>Close</button>
<img data-cart-img class="bgc-menu"></img>
<div class="palette-detail">
<div data-cart-name class="palette-color"></div>
<div data-cart-quantity></div>
<div data-cart-price class="palette-price"></div>
</div>
<!-- <span data-cart-amount class="plz">$0.00</span> -->
</template>
2个回答
根据
此答案
,要定位模板内的元素,您需要使用模板的
content
关键字进行
querySelector
,如下所示:
const template = document.querySelector("#cart-item-template");
const cartRemove = template.content.querySelector("[data-cart-item]");
cartRemove.classList.add("hide"); // Now it works fine
Amadou Beye
2021-07-09
您正尝试在脚本开头引用模板中的元素:
const cartRemove = document.querySelector("[data-cart-item]");
这发生在您的模板被克隆并放入 DOM 之前,因此此时未找到具有属性
data-cart-item
的元素 - 您在
cartRemove
变量中得到
null
。
在
renderCartItems
函数中实例化模板后,尝试通过特定实例选择此元素,就像您在这两行中所做的那样:
const cartItem = cartItemTemplate.content.cloneNode(true);
const container = cartItem.querySelector("[data-cart-item]");
Tomasz
2021-07-09