点击结算按钮时重复添加historyEntry至本地存储的问题求助
Hey there! Let's figure out why you're getting multiple historyEntry entries each time you click checkout. The core issue here is likely duplicate event listeners being attached to your checkout button, plus a couple of small tweaks to make your code more robust.
Looking at your code, you've placed the checkout.addEventListener inside the updateCartItems function. If this function gets called multiple times (like after updating the cart or on page reloads), you're adding a new click listener every time. That means when you click checkout once, all those listeners fire, pushing a historyEntry each time. Also, your Totalprice function is defined and called inside the cart.forEach loop—this makes it run once per cart item, which is totally unnecessary since you only need to calculate the total once per cart update!
Fixes to Resolve the Issue
Here's the revised code with key fixes, plus explanations of what changed:
// Initialize history array properly (avoid null errors) let history = JSON.parse(localStorage.getItem('history')) || []; function updateCartItems() { const cartItemsElement = document.getElementById('middlecart'); const cart = JSON.parse(localStorage.getItem('cart')) || []; // Clear existing cart items first to avoid duplicate renders cartItemsElement.innerHTML = ''; cart.forEach(item => { const qty = item.qty; const price = item.price * qty; const li = document.createElement('div'); // Add your cart item content here (you had this empty in your original code) li.textContent = `${item.name} - Qty: ${qty} - $${price.toFixed(2)}`; cartItemsElement.appendChild(li); }); // Calculate total price ONCE after rendering all cart items calculateTotalPrice(); } function calculateTotalPrice() { const cart = JSON.parse(localStorage.getItem('cart')) || []; let totalPrice = 0; cart.forEach(item => { totalPrice += item.price * item.qty; }); const totalPriceElement = document.getElementById('total-price'); const shipPriceElement = document.getElementById('ship-price'); const finalPriceElement = document.getElementById('final-price'); let ship = 0; totalPriceElement.innerHTML = `$${totalPrice.toFixed(2)}`; if (totalPrice <= 50) { shipPriceElement.innerHTML = `$25`; ship = 25; } else { shipPriceElement.innerHTML = `FREE`; ship = 0; } // Fix: Calculate numeric total first, then format as string const finalPrice = totalPrice + ship; finalPriceElement.innerHTML = `$${finalPrice.toFixed(2)}`; } // Attach checkout listener ONCE, outside updateCartItems to avoid duplicates const checkout = document.getElementById('checkout'); checkout.addEventListener("click", () => { const finalPriceText = document.getElementById('final-price').innerText; const historyEntry = { Finalprice: finalPriceText }; history.push(historyEntry); localStorage.setItem('history', JSON.stringify(history)); localStorage.removeItem("cart"); // Optional: Refresh cart display after clearing updateCartItems(); }); // Log existing history entries history.forEach(orders => { console.log(orders.Finalprice); }); // Call updateCartItems on page load updateCartItems();
Key Changes Explained
- Moved checkout listener: Now it's attached once when the page loads, so no duplicate triggers when
updateCartItemsruns multiple times. - Proper history initialization: Using
|| []ensures we always have a valid array to push to, even if localStorage has no existing history. - Separated total price calculation:
calculateTotalPriceis a standalone function called once after rendering all cart items, eliminating redundant calculations. - Fixed final price math: Your original code was concatenating string-formatted price with a number (e.g., "$49.99" + 25 = "$49.9925")—now we calculate the numeric total first, then format it correctly.
- Cleared cart items before rendering: Added
cartItemsElement.innerHTML = ''to prevent duplicate cart items from showing up ifupdateCartItemsis called multiple times.
备注:内容来源于stack exchange,提问作者Afeef Raza

