<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">简单购物车 · 价格计算</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background: linear-gradient(145deg, #f5f7fa 0%, #e9edf2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
padding: 1.5rem;
margin: 0;
}
.cart-card {
max-width: 760px;
width: 100%;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
background-color: #ffffffdd;
border-radius: 32px;
padding: 2rem 2rem 2.2rem;
box-shadow: 0 20px 36px -8px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.05);
border: 1px solid rgba(255, 255, 255, 0.6);
transition: all 0.2s;
}
h2 {
display: flex;
align-items: center;
gap: 10px;
font-weight: 600;
font-size: 1.8rem;
letter-spacing: -0.02em;
color: #1f2a3a;
margin-bottom: 1.8rem;
border-bottom: 2px solid rgba(0, 0, 0, 0.04);
padding-bottom: 0.75rem;
}
h2 small {
font-size: 1rem;
font-weight: 400;
color: #5b6b7f;
margin-left: auto;
background: #eef2f6;
padding: 0.3rem 0.9rem;
border-radius: 30px;
letter-spacing: 0.3px;
}
.cart-item {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
background: white;
padding: 1rem 1.25rem;
border-radius: 20px;
margin-bottom: 0.9rem;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.02);
border: 1px solid #f0f2f5;
transition: 0.15s ease;
}
.cart-item:hover {
border-color: #cbd5e1;
box-shadow: 0 6px 12px -8px rgba(0, 20, 40, 0.12);
}
.item-info {
display: flex;
align-items: center;
gap: 0.8rem;
flex: 2 1 180px;
}
.item-name {
font-weight: 550;
font-size: 1.15rem;
color: #182230;
}
.item-price {
background: #eef3f9;
padding: 0.2rem 0.8rem;
border-radius: 40px;
font-size: 0.85rem;
font-weight: 500;
color: #2b4b6f;
white-space: nowrap;
}
.qty-control {
display: flex;
align-items: center;
gap: 0.5rem;
background: #f2f5f9;
padding: 0.2rem 0.3rem;
border-radius: 60px;
margin: 0.4rem 0.6rem;
}
.qty-control button {
background: transparent;
border: none;
width: 34px;
height: 34px;
font-size: 1.4rem;
font-weight: 400;
line-height: 1;
color: #2c3e4f;
cursor: pointer;
border-radius: 40px;
transition: 0.1s;
display: inline-flex;
align-items: center;
justify-content: center;
}
.qty-control button:hover {
background: #dce3eb;
color: #0d1b2b;
}
.qty-control button:active {
background: #cbd5e1;
transform: scale(0.92);
}
.qty-num {
min-width: 28px;
text-align: center;
font-weight: 600;
font-size: 1.2rem;
color: #0b1c2e;
}
.item-subtotal {
min-width: 80px;
text-align: right;
font-weight: 600;
font-size: 1.2rem;
color: #1c314b;
letter-spacing: 0.2px;
padding-right: 0.2rem;
}
.delete-btn {
background: none;
border: none;
color: #949faf;
font-size: 1.3rem;
cursor: pointer;
padding: 0 0.2rem 0 0.8rem;
transition: 0.1s;
display: flex;
align-items: center;
}
.delete-btn:hover {
color: #c83a3a;
transform: scale(1.1);
}
.total-section {
margin-top: 2rem;
padding-top: 1.6rem;
border-top: 2px dashed #d0d9e3;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
gap: 0.8rem 1rem;
}
.total-label {
font-size: 1.2rem;
font-weight: 500;
color: #2b4059;
}
.total-amount {
font-size: 2rem;
font-weight: 650;
letter-spacing: -0.02em;
color: #0b1f33;
background: #eef4fa;
padding: 0.2rem 1.2rem;
border-radius: 80px;
}
.reset-btn {
background: #eef2f6;
border: 1px solid #dce3ea;
padding: 0.6rem 1.3rem;
border-radius: 40px;
font-weight: 500;
color: #2e4a66;
cursor: pointer;
transition: 0.15s;
font-size: 0.9rem;
box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}
.reset-btn:hover {
background: #dce5ef;
border-color: #b1c4d8;
color: #001c34;
}
.reset-btn:active {
transform: scale(0.96);
}
.empty-cart {
text-align: center;
padding: 2.2rem 0.5rem;
color: #6a7b90;
font-size: 1rem;
background: #f8faff;
border-radius: 40px;
margin: 0.2rem 0;
}
.hidden {
display: none !important;
}
.footer-note {
margin-top: 1.6rem;
font-size: 0.75rem;
color: #8799ae;
text-align: center;
border-top: 1px solid #e3eaf1;
padding-top: 1.2rem;
}
@media (max-width: 600px) {
.cart-card { padding: 1.5rem; }
.cart-item { flex-wrap: wrap; padding: 0.8rem 0.9rem; }
.item-info { flex-basis: 100%; margin-bottom: 0.4rem; }
.qty-control { margin-left: 0; }
.item-subtotal { min-width: 70px; }
.total-amount { font-size: 1.8rem; }
}
</style>
</head>
<body>
<div class="cart-card" role="main">
<h2>
🛒 购物车
<small id="itemCount">3 件商品</small>
</h2>
<!-- 购物车容器 -->
<div id="cartItemsContainer"></div>
<!-- 底部结算区 -->
<div class="total-section">
<span class="total-label">合计</span>
<span class="total-amount" id="totalPrice">¥0.00</span>
<button class="reset-btn" id="resetCartBtn" aria-label="清空购物车">🗑️ 清空</button>
</div>
<div class="footer-note">点击 +/- 调整数量 · 删除商品</div>
</div>
<script>
(function() {
// ---------- 商品初始数据 ----------
const INIT_ITEMS = [
{ id: 'item1', name: '无线蓝牙耳机', price: 249.00, quantity: 1 },
{ id: 'item2', name: '可折叠支架', price: 89.00, quantity: 2 },
{ id: 'item3', name: 'USB-C 数据线 (1m)', price: 39.90, quantity: 1 },
{ id: 'item4', name: '桌面收纳盒', price: 59.00, quantity: 1 }
];
// 当前状态 (深拷贝)
let cartItems = INIT_ITEMS.map(item => ({ ...item }));
// DOM 元素
const container = document.getElementById('cartItemsContainer');
const totalPriceEl = document.getElementById('totalPrice');
const itemCountEl = document.getElementById('itemCount');
const resetBtn = document.getElementById('resetCartBtn');
// ---------- 渲染购物车 ----------
function renderCart() {
// 过滤掉数量 <= 0 的商品(防御)
cartItems = cartItems.filter(item => item.quantity > 0);
// 如果购物车为空,显示空状态
if (cartItems.length === 0) {
container.innerHTML = `<div class="empty-cart">🛍️ 购物车是空的,点击「清空」恢复默认商品</div>`;
updateTotalAndCount();
return;
}
// 生成每个商品条目 HTML
let html = '';
cartItems.forEach(item => {
const subtotal = item.price * item.quantity;
html += `
<div class="cart-item" data-id="${item.id}">
<div class="item-info">
<span class="item-name">${escapeHtml(item.name)}</span>
<span class="item-price">¥${item.price.toFixed(2)}</span>
</div>
<div class="qty-control">
<button class="qty-btn minus" data-id="${item.id}" aria-label="减少数量">−</button>
<span class="qty-num">${item.quantity}</span>
<button class="qty-btn plus" data-id="${item.id}" aria-label="增加数量">+</button>
</div>
<span class="item-subtotal">¥${subtotal.toFixed(2)}</span>
<button class="delete-btn" data-id="${item.id}" aria-label="删除商品">✕</button>
</div>
`;
});
container.innerHTML = html;
updateTotalAndCount();
// 重新绑定事件 (事件委托在容器上, 但为了防止内存溢出, 使用容器监听)
// 已经在外部使用委托, 无需再绑定
}
// 简单的转义 (防止XSS 但数据可信, 仅做演示)
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ---------- 更新总计和数量徽章 ----------
function updateTotalAndCount() {
const total = cartItems.reduce((sum, item) => sum + (item.price * item.quantity), 0);
totalPriceEl.textContent = `¥${total.toFixed(2)}`;
const count = cartItems.reduce((sum, item) => sum + item.quantity, 0);
itemCountEl.textContent = `${count} 件商品`;
}
// ---------- 核心操作: 修改数量 / 删除 ----------
function handleItemAction(target) {
// 通过匹配最近的 .cart-item 获取商品 id
const cartItemDiv = target.closest('.cart-item');
if (!cartItemDiv) return;
const id = cartItemDiv.dataset.id;
if (!id) return;
// 寻找商品索引
const index = cartItems.findIndex(item => item.id === id);
if (index === -1) return;
// 判断操作类型
if (target.classList.contains('plus')) {
// 增加数量 (上限 99)
if (cartItems[index].quantity < 99) {
cartItems[index].quantity += 1;
} else {
alert('数量最多为 99');
return;
}
renderCart();
}
else if (target.classList.contains('minus')) {
// 减少数量 (最少为 1, 减到0则删除)
if (cartItems[index].quantity > 1) {
cartItems[index].quantity -= 1;
} else {
// 数量为1 再减→移除
cartItems.splice(index, 1);
}
renderCart();
}
else if (target.classList.contains('delete-btn')) {
// 直接删除该商品
cartItems.splice(index, 1);
renderCart();
}
}
// ---------- 重置购物车 (清空后恢复默认) ----------
function resetCartToDefault() {
cartItems = INIT_ITEMS.map(item => ({ ...item }));
renderCart();
}
// ---------- 事件监听 (利用事件委托) ----------
container.addEventListener('click', function(e) {
const target = e.target.closest('button');
if (!target) return;
// 只处理购物车容器内的按钮 (plus, minus, delete)
if (target.classList.contains('qty-btn') || target.classList.contains('delete-btn')) {
e.preventDefault();
handleItemAction(target);
}
});
// 重置按钮
resetBtn.addEventListener('click', function(e) {
resetCartToDefault();
});
// ---------- 初始化渲染 ----------
renderCart();
// 附加: 若用户误触键盘等, 保持界面统一
console.log('✅ 简单购物车已启动 — 点击 +/- 修改数量,✕ 删除商品');
})();
</script>
</body>
</html>
购物车价格计算逻辑
您可以通过调整数量或删除商品,实时查看总价变化。

- 商品管理与数量调整:每个商品都配有“+/-”按钮,点击可增加或减少购买数量,当数量减至0时,该商品会自动从购物车中移除。
- 实时价格计算:每个商品的行小计和页面底部的“合计”金额会随您调整数量而立即更新,无需手动刷新。
- 购物车重置:如果您想重新开始,可以点击“清空”按钮,购物车将恢复为默认的商品列表和数量。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播