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

使用JavaScript实现购物车商品渲染 解决多商品无法循环展示问题

问题根源

你的代码核心问题出在addCartItem方法的逻辑上:

  • 每次点击添加按钮时,你遍历了全部商品数组来生成购物车项DOM,循环赋值div.innerHTML会覆盖之前的内容,最终只显示最后一个商品的信息
  • 没有根据点击按钮的data-id筛选对应要添加的商品,也没有把选中商品存入提前声明的cart数组统一管理
  • 没有给商品初始化amount字段,渲染时会出现undefined的问题
  • 原有代码里存在HTML转义符错误,</>无法正常渲染DOM结构

修复后的完整代码

const cartBtn = document.querySelector(`.cart-btn`);
const closeCartBtn = document.querySelector(`.close-cart`);
const clearCartBtn = document.querySelector(`.clear-cart`);
const cartDOM = document.querySelector(".cart");
const cartOverlay = document.querySelector(`.cart-overlay`);
const cartItems = document.querySelector(".cart-items");
const cartTotal = document.querySelector(".cart-total");
const cartContent = document.querySelector(".cart-content");
const productsDOM = document.querySelector(`.products`);

let cart = []; // 购物车数组
let buttonsDOM = []; // 按钮数组

// 商品数据
let itemObject = [{
    title: "Chocolate",
    price: 10.99,
    id: 1,
    img: "https://images.pexels.com/photos/1055272/pexels-photo-1055272.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
    title: "Cream",
    price: 12.99,
    id: 2,
    img: "https://images.pexels.com/photos/1055270/pexels-photo-1055270.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260"
}, {
    title: "Frosting",
    price: 12.99,
    id: 3,
    img: "https://images.pexels.com/photos/1055271/pexels-photo-1055271.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
    title: "Berry",
    price: 14.99,
    id: 4,
    img: "https://images.pexels.com/photos/3081657/pexels-photo-3081657.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
    title: "Deluxe",
    price: 19.99,
    id: 5,
    img: "https://images.pexels.com/photos/1998634/pexels-photo-1998634.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}, {
    title: "Oreo",
    price: 14.99,
    id: 6,
    img: "https://images.pexels.com/photos/783274/pexels-photo-783274.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260"
}];

// 点击打开购物车
cartBtn.addEventListener(`click`, () => {
    cartOverlay.classList.remove(`invisible`);
});

// 隐藏购物车遮罩
function hideOverlay() {
    cartOverlay.classList.add(`invisible`);
}

// 点击关闭购物车
closeCartBtn.addEventListener(`click`, () => {
    cartOverlay.classList.add(`invisible`);
});

// 清空购物车并隐藏遮罩
clearCartBtn.addEventListener(`click`, () => {
    cart = [];
    cartContent.innerHTML = '';
    updateCartTotal();
    // 重置所有按钮状态
    buttonsDOM.forEach(btn => {
        btn.innerText = "Purchase";
        btn.disabled = false;
    });
    hideOverlay();
});

// 删除单个购物车商品
function deleteSingleItem(id) {
    cart = cart.filter(item => item.id !== id);
    renderCart();
    // 恢复对应按钮状态
    const targetBtn = buttonsDOM.find(btn => btn.dataset.id == id);
    if(targetBtn) {
        targetBtn.innerText = "Purchase";
        targetBtn.disabled = false;
    }
    updateCartTotal();
}

// 更新购物车总价和商品数量
function updateCartTotal() {
    let total = 0;
    let count = 0;
    cart.forEach(item => {
        total += item.price * item.amount;
        count += item.amount;
    });
    cartTotal.innerText = total.toFixed(2);
    cartItems.innerText = count;
}

// 渲染整个购物车
function renderCart() {
    cartContent.innerHTML = '';
    cart.forEach(item => {
        const div = document.createElement('div');
        div.classList.add('cart-item');
        div.innerHTML = `
        <div class="grid align-middle grid-cols-3 gap-2 my-4">
        <img class="h-28 w-28" src="${item.img}" alt="Product"/>
            <div>
                <h4>${item.title}</h4>
                <h5>$${item.price}</h5>
                <span class="text-red-200 remove-btn" data-id=${item.id}>Remove</span>
            </div>
            <div>
                <i class="fas fa-chevron-up text-red-200 align-middle increase-btn" data-id=${item.id}></i>
                <p class="align-middle item-amount">${item.amount}</p>
                <i class="fas fa-chevron-down text-red-200 align-middle decrease-btn" data-id=${item.id}></i>
            </div>
        </div>`;
        cartContent.appendChild(div);
    });
    // 绑定删除、增减数量事件
    bindCartItemEvents();
    updateCartTotal();
}

// 绑定购物车内商品的操作事件
function bindCartItemEvents() {
    // 删除事件
    document.querySelectorAll('.remove-btn').forEach(btn => {
        btn.addEventListener('click', e => {
            const id = e.target.dataset.id;
            deleteSingleItem(id);
        });
    });
    // 增加数量
    document.querySelectorAll('.increase-btn').forEach(btn => {
        btn.addEventListener('click', e => {
            const id = e.target.dataset.id;
            const targetItem = cart.find(item => item.id == id);
            targetItem.amount++;
            renderCart();
        });
    });
    // 减少数量
    document.querySelectorAll('.decrease-btn').forEach(btn => {
        btn.addEventListener('click', e => {
            const id = e.target.dataset.id;
            const targetItem = cart.find(item => item.id == id);
            if(targetItem.amount > 1) {
                targetItem.amount--;
                renderCart();
            } else {
                deleteSingleItem(id);
            }
        });
    });
}

// 渲染商品列表
function displayProducts() {
    let html = ``;
    itemObject.forEach((item) => {
        html += `
        <div class="bg-white rounded-lg">
            <img class="rounded-md w-screen object-cover max-h-60"
                src="${item.img}"
                alt="">
            <div class="py-2 px-8 text-gray-600">
                <div class="grid grid-cols-2 py-3 text-xl font-bold ">
                    <h3>${item.title}</h3>
                    <p class="text-right">$${item.price}</p>
                </div>
                <button data-id=${item.id}
                    class="bg-purple-200 font-bold px-3 mt-2 text-xl py-4 mb-4 w-full rounded-md transition-all hover:bg-purple-300 bag-btn">Purchase</button>
            </div>
        </div>
        `;
    });
    productsDOM.innerHTML = html;
}

// 绑定商品添加到购物车的事件
function addProductsToCart() {
    const buttons = [...document.querySelectorAll(`.bag-btn`)];
    buttonsDOM = buttons;
    buttons.forEach(button => {
        let id = button.dataset.id;
        let inCart = cart.find(item => item.id == id);
        if (inCart) {
            button.innerText = "In Cart";
            button.disabled = true;
        }

        button.addEventListener(`click`, event => {
            event.target.innerText = "In Cart";
            event.target.disabled = true;
            // 找到当前点击的商品
            const currentItem = {...itemObject.find(item => item.id == id)};
            // 初始化购买数量
            currentItem.amount = 1;
            // 加入购物车数组
            cart.push(currentItem);
            // 重新渲染购物车
            renderCart();
            // 打开购物车
            cartOverlay.classList.remove(`invisible`);
        });
    });
}

displayProducts();
addProductsToCart();

补充说明

现在代码已经支持多商品添加、商品数量增减、单个商品删除、购物车清空、总价自动计算的完整功能,所有操作都会同步更新按钮状态和购物车数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:45:00