You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

购物网站数量选择器代码重复问题:如何复用代码减少冗余?

问题:购物网站数量选择器代码重复,如何复用?

我开发了一个购物网站,但每个Quantity selector(数量选择器)都需要单独编写代码,导致大量重复代码。请问如何为每个数量选择器复用相同的代码?

网站截图

以下是补充代码(因Stack Overflow不允许仅以代码为主提问,即便我的问题是如何减少代码量):

<tr>
    <td>
        <span id="price_log">2.23</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <span id="price_leaf">0.28</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <span id="price_stone">0.14</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <span id="price_melon">2.80</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
</tr>
<tr>
    <td>
        <input type="button" value="-" onclick="updateQuantity('log', -1)">
        <input type="number" id="log" value="0" min="0" onchange="updateQuantity('log', 0)">
        <input type="button" value="+" onclick="updateQuantity('log', 1)">
        <br>
        Total: <span id="total_log">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <input type="button" value="-" onclick="updateQuantity('leaf', -1)">
        <input type="number" id="leaf" value="0" min="0" onchange="updateQuantity('leaf', 0)">
        <input type="button" value="+" onclick="updateQuantity('leaf', 1)">
        <br>
        Total: <span id="total_leaf">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <input type="button" value="-" onclick="updateQuantity('stone', -1)">
        <input type="number" id="stone" value="0" min="0" onchange="updateQuantity('stone', 0)">
        <input type="button" value="+" onclick="updateQuantity('stone', 1)">
        <br>
        Total: <span id="total_stone">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td>
        <input type="button" value="-" onclick="updateQuantity('melon', -1)">
        <input type="number" id="melon" value="0" min="0" onchange="updateQuantity('melon', 0)">
        <input type="button" value="+" onclick="updateQuantity('melon', 1)">
        <br>
        Total: <span id="total_melon">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
</tr>

解决方案

1. 用数据属性+事件委托减少重复代码

先修改HTML结构,用**数据属性(data-*)**关联商品信息,去掉硬编码的onclick/onchange,改用事件委托监听父容器的事件,实现通用逻辑:

修改后的HTML:

<tr>
    <td data-product="log">
        <span class="price">2.23</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="leaf">
        <span class="price">0.28</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="stone">
        <span class="price">0.14</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="melon">
        <span class="price">2.80</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
</tr>
<tr id="quantity-container">
    <td data-product="log">
        <input type="button" value="-" class="quantity-btn" data-action="decrease">
        <input type="number" class="quantity-input" value="0" min="0">
        <input type="button" value="+" class="quantity-btn" data-action="increase">
        <br>
        Total: <span class="total">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="leaf">
        <input type="button" value="-" class="quantity-btn" data-action="decrease">
        <input type="number" class="quantity-input" value="0" min="0">
        <input type="button" value="+" class="quantity-btn" data-action="increase">
        <br>
        Total: <span class="total">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="stone">
        <input type="button" value="-" class="quantity-btn" data-action="decrease">
        <input type="number" class="quantity-input" value="0" min="0">
        <input type="button" value="+" class="quantity-btn" data-action="increase">
        <br>
        Total: <span class="total">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
    <td data-product="melon">
        <input type="button" value="-" class="quantity-btn" data-action="decrease">
        <input type="number" class="quantity-input" value="0" min="0">
        <input type="button" value="+" class="quantity-btn" data-action="increase">
        <br>
        Total: <span class="total">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    </td>
</tr>

对应的通用JavaScript:

// 监听增减按钮点击
document.getElementById('quantity-container').addEventListener('click', function(e) {
    const target = e.target;
    if (!target.classList.contains('quantity-btn')) return;

    const productTd = target.closest('[data-product]');
    const productName = productTd.dataset.product;
    const input = productTd.querySelector('.quantity-input');
    const price = parseFloat(document.querySelector(`[data-product="${productName}"] .price`).textContent);
    const totalSpan = productTd.querySelector('.total');

    let quantity = parseInt(input.value);
    quantity = target.dataset.action === 'increase' ? quantity + 1 : Math.max(0, quantity - 1);
    
    input.value = quantity;
    totalSpan.textContent = (quantity * price).toFixed(2);
});

// 监听输入框直接修改
document.getElementById('quantity-container').addEventListener('change', function(e) {
    const target = e.target;
    if (!target.classList.contains('quantity-input')) return;

    const productTd = target.closest('[data-product]');
    const productName = productTd.dataset.product;
    const price = parseFloat(document.querySelector(`[data-product="${productName}"] .price`).textContent);
    const totalSpan = productTd.querySelector('.total');

    let quantity = parseInt(target.value);
    quantity = isNaN(quantity) ? 0 : Math.max(0, quantity);
    
    target.value = quantity;
    totalSpan.textContent = (quantity * price).toFixed(2);
});

2. 封装模板动态生成(适合新增商品场景)

如果后续要加更多商品,可以把数量选择器封装成模板,通过JavaScript循环生成,彻底避免重复写HTML:

第一步:定义商品数据

const products = [
    { name: 'log', price: 2.23 },
    { name: 'leaf', price: 0.28 },
    { name: 'stone', price: 0.14 },
    { name: 'melon', price: 2.80 }
];

第二步:动态生成HTML结构

const table = document.querySelector('table');

// 生成价格行
const priceRow = document.createElement('tr');
products.forEach(prod => {
    const td = document.createElement('td');
    td.dataset.product = prod.name;
    td.innerHTML = `
        <span class="price">${prod.price.toFixed(2)}</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    `;
    priceRow.appendChild(td);
});
table.appendChild(priceRow);

// 生成数量选择器行
const quantityRow = document.createElement('tr');
quantityRow.id = 'quantity-container';
products.forEach(prod => {
    const td = document.createElement('td');
    td.dataset.product = prod.name;
    td.innerHTML = `
        <input type="button" value="-" class="quantity-btn" data-action="decrease">
        <input type="number" class="quantity-input" value="0" min="0">
        <input type="button" value="+" class="quantity-btn" data-action="increase">
        <br>
        Total: <span class="total">0.00</span>
        <img src="ShopStuff/gold_coin.png" style="width:20px; height:20px;">
    `;
    quantityRow.appendChild(td);
});
table.appendChild(quantityRow);

最后复用上面的事件委托JavaScript代码即可,新增商品只需修改products数组,无需重复编写HTML结构。

核心思路

  • 用类选择器替代唯一ID,避免硬编码;
  • 用数据属性关联商品信息,让代码动态识别不同商品;
  • 用事件委托监听父容器,减少事件绑定数量;
  • 封装通用逻辑或模板,新增商品只需添加数据,无需重复写结构。

内容的提问来源于stack exchange,提问作者Spleefies

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:27:03