核心問題
- JSP 循環輸出多個商品,**ID 重複** (如
id="text_box1"、id="total1") → JS document.getElementById 只能獲取第一個,導致增減數量、計算總價失效。
- 單價顯示在
<label id="total1">,增減數量時直接覆蓋單價而非計算小計。
- JS 代碼重複、硬編碼 ID、無法擴展。
修正方案:類選擇器 + data-* 屬性 + 事件委托
1. JSP 輸出模板 (關鍵修改)
<table class="cart-table">
<thead>
<tr><th>選擇</th><th>圖片</th><th>名稱</th><th>單價</th><th>數量</th><th>小計</th><th>操作</th></tr>
</thead>
<tbody>
<% for (int i=0; i
2. 統一 JS 邏輯 (jQuery 事件委托)
$(function() {
const $table = $('.cart-table');
const $summary = $('#totalPrice');
const $qtySum = $('#totalQty');
// 增加數量
$table.on('click', '.btn-inc', function() {
const $row = $(this).closest('.cart-row');
const $qty = $row.find('.qty');
const price = parseFloat($row.data('price')) || 0;
const newQty = parseInt($qty.val()) + 1;
$qty.val(newQty);
updateRow($row, price, newQty);
});
// 減少數量
$table.on('click', '.btn-dec', function() {
const $row = $(this).closest('.cart-row');
const $qty = $row.find('.qty');
const price = parseFloat($row.data('price')) || 0;
let newQty = parseInt($qty.val()) - 1;
if (newQty < 1) newQty = 1;
$qty.val(newQty);
updateRow($row, price, newQty);
});
// 核心計算函數
function updateRow($row, price, qty) {
const subtotal = (price * qty).toFixed(2);
$row.find('.subtotal').text(subtotal);
$row.find('.item-chk').val(subtotal); // 讓全選計算用 value 存小計
recalcTotal();
}
// 全選/反選/刪除/結算... (略)
function recalcTotal() {
let total = 0, count = 0;
$table.find('.item-chk:checked').each(function() {
total += parseFloat($(this).val()) || 0;
count++;
});
$summary.text(total.toFixed(2));
$qtySum.text(count);
}
$table.on('change', '.item-chk', recalcTotal);
$('#chkAll').on('change', function() {
$table.find('.item-chk').prop('checked', this.checked).trigger('change');
});
});
關鍵修復點總結
| 問題 | 修復 |
| ID 重複導致 JS 只操作第一行 |
改用 類選擇器 + 最近祖先行定位 (closest('.cart-row')) |
| 單價被覆蓋 |
單價只讀顯示在 .price,**新增 .subtotal 列** 存放數量×單價 |
| JS 代碼重複 (每行一套) |
事件委托 一套代碼處理所有行 |
| 全選計算錯誤 |
Checkbox value 存儲該行小計,全選時累加 value |
進階建議
- 將購物車數據存入 Session/Redis,頁面渲染改為純前端模板 (Vue/React/jQuery Template) + AJAX 獲取 JSON。
- 數量輸入框改為
readonly,強制通過 +/- 按鈕修改,避免非法輸入。
- 結算時後端重新驗證價格、庫存,防止前端篡改。