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

JavaScript购物车开发:如何更新各SKU的数量与总价?

完整解决方案与优化建议

核心代码实现

1. 纯数据逻辑的Cart类(无DOM交互)

class Cart {
  constructor() {
    this.items = new Map(); // 用Map按SKU快速定位商品,性能优于数组
  }

  // 添加商品:数量+1,无则初始化
  addItem(sku, title, price) {
    if (this.items.has(sku)) {
      const item = this.items.get(sku);
      item.quantity += 1;
    } else {
      this.items.set(sku, { sku, title, price, quantity: 1 });
    }
    return this.getTotal();
  }

  // 减少商品数量:最低为0,数量为0时可选移除商品
  subtractItem(sku) {
    if (!this.items.has(sku)) return this.getTotal();
    const item = this.items.get(sku);
    item.quantity = Math.max(item.quantity - 1, 0);
    if (item.quantity === 0) this.items.delete(sku);
    return this.getTotal();
  }

  // 获取单个商品小计
  getItemTotal(sku) {
    const item = this.items.get(sku);
    return item ? item.price * item.quantity : 0;
  }

  // 获取购物车总价
  getTotal() {
    return Array.from(this.items.values()).reduce((sum, item) => {
      return sum + item.price * item.quantity;
    }, 0);
  }

  // 获取所有商品列表
  getItems() {
    return Array.from(this.items.values());
  }
}

2. DOM操作与事件处理

// 初始化实例与DOM元素
const cart = new Cart();
const cartItemsContainer = document.getElementById('cart-items');
const cartTotalElement = document.getElementById('cart-total');

// 渲染购物车商品到页面
function renderCartItems() {
  cartItemsContainer.innerHTML = '';
  const items = cart.getItems();

  items.forEach(item => {
    const itemElement = document.createElement('div');
    itemElement.className = 'cart-item';
    itemElement.dataset.sku = item.sku; // 存储SKU到DOM属性,方便事件关联

    itemElement.innerHTML = `
      <div class="item-info">
        <h3>${item.title}</h3>
        <p>单价: $${item.price.toFixed(2)}</p>
      </div>
      <div class="quantity-controls">
        <button class="subtract-btn">-</button>
        <span class="quantity">${item.quantity}</span>
        <button class="add-btn">+</button>
      </div>
      <div class="item-total">小计: $${cart.getItemTotal(item.sku).toFixed(2)}</div>
    `;

    cartItemsContainer.appendChild(itemElement);
  });
}

// 更新购物车整体显示
function updateCartDisplay() {
  renderCartItems();
  cartTotalElement.textContent = `总价: $${cart.getTotal().toFixed(2)}`;
}

// 事件委托:统一绑定到容器,减少内存占用
cartItemsContainer.addEventListener('click', (e) => {
  const target = e.target;
  const itemElement = target.closest('.cart-item');
  if (!itemElement) return;

  const sku = itemElement.dataset.sku;
  const item = cart.getItems().find(i => i.sku === sku);
  if (!item) return;

  if (target.classList.contains('add-btn')) {
    cart.addItem(sku, item.title, item.price);
  } else if (target.classList.contains('subtract-btn')) {
    cart.subtractItem(sku);
  }
  updateCartDisplay();
});

// 示例:初始添加商品
cart.addItem('SKU001', '纯棉T恤', 29.99);
cart.addItem('SKU002', '休闲牛仔裤', 79.99);
updateCartDisplay();

配套HTML结构

<div id="cart-items"></div>
<div id="cart-total"></div>

你的疑问解答

1. 为商品列表创建DOM元素

  • 用document.createElement()创建单个商品容器,通过dataset.sku存储商品标识,方便后续事件关联。
  • 用innerHTML快速构建商品内部结构(标题、控件、小计),复杂场景也可逐个用createElement创建子元素。
  • 最后将商品容器追加到购物车父容器中。

2. 监听按钮事件更新商品数量

  • 采用事件委托:将点击事件绑定到购物车父容器,而非每个按钮单独绑定,减少内存开销。
  • 通过closest('.cart-item')定位当前操作的商品项,从dataset.sku获取商品标识,调用Cart类的addItem/subtractItem方法更新数据。

3. 变更时更新DOM中的总价

  • Cart类提供getTotal()计算全局总价,getItemTotal(sku)计算单个商品小计。
  • 每次数据变更后调用updateCartDisplay(),统一重新渲染商品列表并更新总价元素内容。

代码优化建议

  1. 单一职责原则:Cart类只负责数据逻辑,DOM操作完全分离,后续可轻松复用或编写单元测试。
  2. 性能优化:用Map存储商品,通过SKU快速查找,比数组遍历效率更高;事件委托减少事件绑定数量。
  3. 用户体验优化:用toFixed(2)格式化金额为两位小数,避免显示多位小数;数量减少时限制最小值为0,防止出现负数。
  4. 防抖优化:如果购物车操作频繁,可给updateCartDisplay()添加防抖函数,避免短时间内多次渲染DOM:
    const debounce = (fn, delay) => {
      let timer;
      return (...args) => {
        clearTimeout(timer);
        timer = setTimeout(() => fn.apply(this, args), delay);
      };
    };
    const debouncedUpdate = debounce(updateCartDisplay, 100);
    // 事件中调用debouncedUpdate替代updateCartDisplay
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:37:14