JavaScript购物车:添加新商品时输入元素计数器值重置问题修复
问题描述
我一直在调试以下代码,但始终无法达到预期效果:
现有JS代码
var milo = document.getElementById('milo'); var ovaltine = document.getElementById('ovaltine'); var bournvita = document.getElementById('bournvita'); var miloPrice = 2000.00; var ovaltinePrice = 1500.00; var bournvitaPrice = 1850.00; var milocounter = 0; var miloAmount = 0; var ovaltinecounter = 0; var ovaltineAmount; var bournvitacounter = 0; var bournvitaAmount = 0; milo.addEventListener('click', function(){ if (milocounter == 0) { milocounter += 1; miloAmount = miloPrice * milocounter; cartdetails.innerHTML += '<tr>' + '<td><input type="text" id="formilocounter" value="' + milocounter +'"></td>' + '<td><input type="text" id="formiloamount" value="' + miloAmount +'"></td>' + '</tr>' + '<br>'; } else { milocounter += 1; miloAmount = miloPrice * milocounter; var formilocounter = document.getElementById('formilocounter'); var formiloamount = document.getElementById('formiloamount'); formilocounter.value = milocounter; formiloamount.value = miloAmount; } }); ovaltine.addEventListener('click', function(){ if (ovaltinecounter == 0) { ovaltinecounter += 1; ovaltineAmount = ovaltinePrice * ovaltinecounter; cartdetails.innerHTML += '<tr>' + '<td><input type="text" id="forovaltinecounter" value="' + ovaltinecounter +'"></td>' + '<td><input type="text" id="forovaltineamount" value="' + ovaltineAmount +'"></td>' + '</tr>' + '<br>'; } else { ovaltinecounter += 1; ovaltineAmount = ovaltinePrice * ovaltinecounter; var forovaltinecounter = document.getElementById('forovaltinecounter'); var forovaltineamount = document.getElementById('forovaltineamount'); forovaltinecounter.value = ovaltinecounter; forovaltineamount.value = ovaltineAmount; } }); bournvita.addEventListener('click', function(){ if (bournvitacounter == 0) { bournvitacounter += 1; bournvitaAmount = bournvitaPrice * bournvitacounter; cartdetails.innerHTML += '<tr>' + '<td ><input type="text" id="forbournvitacounter" value="' + bournvitacounter +'"></td>' + '<td ><input type="text" id="forbournvitaamount" value="' + bournvitaAmount +'"></td>' + '</tr>' + '<br>'; } else { bournvitacounter += 1; bournvitaAmount = bournvitaPrice * bournvitacounter; var forbournvitacounter = document.getElementById('forbournvitacounter'); var forbournvitaamount = document.getElementById('forbournvitaamount'); forbournvitacounter.value = bournvitacounter; forbournvitaamount.value = bournvitaAmount; } });
现有HTML代码
<article> <div id="milo" > <img src="images/milo.jfif"><br> <label>2,000.00</label> </div> <div id="ovaltine"> <img src="images/ovaltine.jfif"><br> <label >1,500.00</label> </div> <div id="bournvita"> <img src="images/bournvita.jfif"><br> <label>1,850.00</label> </div> </article> <div id="cartdetails"> </div>
当前异常表现
点击任意商品首次添加及重复点击同一件商品时,功能正常;但点击另一件新商品时,之前已添加商品的输入框计数器会被重置为1,再次点击该商品时又会恢复正确计数。需要实现添加新商品时,所有已添加商品的计数器值保持不变。
解决方案
问题根源
使用cartdetails.innerHTML += ...拼接HTML时,浏览器会重新解析整个容器内的DOM结构,已存在的输入框会被重新创建,导致它们的value丢失,变回初始的1。
修改后的代码
JS代码
// 统一管理商品数据,减少重复逻辑 const products = [ { id: 'milo', price: 2000.00, counter: 0, row: null }, { id: 'ovaltine', price: 1500.00, counter: 0, row: null }, { id: 'bournvita', price: 1850.00, counter: 0, row: null } ]; const cartDetails = document.getElementById('cartdetails'); // 为每个商品绑定点击事件 products.forEach(product => { const el = document.getElementById(product.id); el.addEventListener('click', () => { product.counter += 1; const amount = product.price * product.counter; if (!product.row) { // 首次添加,动态创建DOM元素 const tr = document.createElement('tr'); // 创建计数器输入框 const counterTd = document.createElement('td'); const counterInput = document.createElement('input'); counterInput.type = 'text'; counterInput.value = product.counter; counterTd.appendChild(counterInput); // 创建金额输入框 const amountTd = document.createElement('td'); const amountInput = document.createElement('input'); amountInput.type = 'text'; amountInput.value = amount; amountTd.appendChild(amountInput); tr.appendChild(counterTd); tr.appendChild(amountTd); // 保存DOM引用,方便后续更新 product.row = tr; product.counterInput = counterInput; product.amountInput = amountInput; // 添加到购物车容器 cartDetails.appendChild(tr); cartDetails.appendChild(document.createElement('br')); } else { // 更新已有商品的计数和金额 product.counterInput.value = product.counter; product.amountInput.value = amount; } }); });
HTML代码(无需改动)
<article> <div id="milo" > <img src="images/milo.jfif"><br> <label>2,000.00</label> </div> <div id="ovaltine"> <img src="images/ovaltine.jfif"><br> <label >1,500.00</label> </div> <div id="bournvita"> <img src="images/bournvita.jfif"><br> <label>1,850.00</label> </div> </article> <div id="cartdetails"></div>
改动说明
- 统一商品数据管理:将所有商品的ID、价格、计数器、DOM引用整合到数组中,避免重复代码,后续扩展商品更便捷。
- 动态创建DOM:使用
document.createElement生成元素并添加到容器,不会破坏已有的DOM节点,原有输入框的数值不会丢失。 - 保存DOM引用:首次创建元素后,将其存入商品对象,后续点击时直接更新元素值,无需再次查找DOM,提升性能。
内容的提问来源于stack exchange,提问作者Adewuyi
相关产品推荐
相关产品推荐

