

统一声明:
1.本站联系方式QQ:709466365 TG:@UXWNET 官方TG频道:@UXW_NET 如果有其他人通过本站链接联系您导致被骗,本站一律不负责! 2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET 3.免实名域名注册购买- 游侠云域名 4.免实名国外服务器购买- 游侠网云服务
我们从0到1,手把手教你实现一个完整的购物车:先搭好HTML结构和基础样式,再一步步写JS逻辑——商品怎么动态渲染?数量增减怎么联动数据?总价怎么实时更新?选中商品怎么统计?每一步都有详细代码+通俗讲解,没有复杂黑科技,新手跟着敲就能懂。更重要的是,这个购物车不是“玩具”——它包含了实际项目里常用的核心功能,做完就能直接用到你的小项目里。
不管你是刚学JS的新手,还是想补全实战能力的学习者,跟着这篇教程走,保证你能亲手做出一个能落地的购物车,把“纸上的JS知识”变成“能跑的交互功能”,成就感直接拉满!
你有没有过这种情况?学JS的时候跟着教程做购物车,要么代码copy过来能跑但根本不懂逻辑,要么做完只有个空架子,连数量增减都不联动总价?我去年帮朋友的社区团购小站做购物车时,就遇到过这问题——他找了个教程跟着做,结果用户点“+”号,数量涨了但总价没变,反馈全是骂人的。后来我帮他重构了一遍,把“数据驱动界面”的逻辑理清楚,才解决了问题。今天我就把当时的步骤拆解给你,不用懂复杂的框架,纯JS就能做,做完直接能用在小项目里。
先理清楚:购物车界面到底要实现哪些核心功能?
很多新手刚学的时候,总想着“做个好看的界面”,但实际项目里,功能的合理性比样式重要10倍。我帮朋友做的时候,一开始没明确核心功能,导致做了很多无用功——比如先加了商品分类筛选,结果用户根本用不上,反而把购物车搞得很复杂。后来我查了几个小电商站的购物车,又问了做前端的朋友,才 出购物车的5个必做核心功能:
为了让你更清楚“功能和数据的对应关系”,我做了张表格——你看,每个功能都对应着具体的数据字段,后面写代码时直接“对号入座”就行:
核心功能 | 对应数据字段 | 用户操作场景 |
---|---|---|
商品展示 | id/name/price/imgUrl | 用户打开购物车看商品 |
数量增减 | quantity | 用户想多买/少买几件 |
总价计算 | price/quantity/isChecked | 用户想知道要付多少钱 |
选中状态 | isChecked | 用户想选/不选某件商品 |
记住:所有操作都要先修改数据,再渲染界面——我之前犯过“直接改DOM”的错,比如用户点“+”号,我直接把输入框的value加1,但数据数组里的quantity没改,结果后面计算总价时,用的还是原来的数量,导致“界面和数据不一致”的bug。后来改成“先改数据,再重新渲染”,就再也没出现过这种问题。
手把手写代码:从0到1实现能落地的购物车
现在开始写代码——我尽量把每一步的逻辑讲透,你跟着敲就行,有疑问的地方可以标出来,后面留言问我。
第一步:搭HTML结构——越简洁越好
先写基础的HTML,核心是“购物车容器”和“商品项模板”。我一般会用语义化标签,比如用
放商品列表,
我的购物车
<!-商品列表容器 >
然后,每个商品项的HTML我会用JS动态生成(后面讲),但你要先想清楚商品项里要包含哪些元素:
我给每个元素加了明确的类名,比如.cart-item
代表商品项,.item-check
代表勾选框——别用.box1
.btn2
这种命名,不然过一周你自己都忘了哪个是哪个。
第二步:写CSS基础样式——先保证功能能用
样式不用太复杂,先做“能用的布局”,后面再调美观。我用Flex布局做商品项的排列,这样能快速实现“图片左、信息中、数量右”的结构:
.cart-container {
width: 800px;
margin: 50px auto;
border: 1px solid #eee;
padding: 20px;
}
.cart-title {
font-size: 18px;
margin-bottom: 20px;
}
.cart-item {
display: flex;
align-items: center;
padding: 15px 0;
border-bottom: 1px solid #eee;
}
.item-check {
margin-right: 15px;
}
.item-img {
width: 80px;
height: 80px;
object-fit: cover;
margin-right: 15px;
}
.item-info {
flex: 1; / 占剩余空间 /
}
.item-name {
font-size: 16px;
margin-bottom: 10px;
}
.item-price {
font-size: 14px;
color: #ff5722;
}
.item-quantity {
display: flex;
align-items: center;
margin-right: 30px;
}
.quantity-btn {
width: 30px;
height: 30px;
border: 1px solid #ddd;
background: #fff;
cursor: pointer;
}
.quantity-input {
width: 50px;
height: 30px;
text-align: center;
border: 1px solid #ddd;
margin: 0 5px;
}
.item-delete {
background: #ff4444;
color: #fff;
border: none;
padding: 5px 10px;
cursor: pointer;
}
.cart-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #eee;
}
.total-price {
font-size: 18px;
color: #ff5722;
font-weight: bold;
}
.checkout-btn {
background: #ff5722;
color: #fff;
border: none;
padding: 10px 20px;
cursor: pointer;
}
注意:数量输入框要加min="1"
的限制——我之前没加,用户把数量改成0,导致总价变成负数,朋友差点被投诉。
第三步:写JS逻辑——分模块,别堆在一起
JS是购物车的“大脑”,我会把逻辑分成4个模块:数据初始化、渲染商品、绑定事件、计算总价。这样后期维护的时候,找问题也方便。
真实项目里,购物车数据是从后端接口拿的,但新手可以用数组+对象模拟:
// 购物车数据源(模拟后端返回的数据)
const cartData = [
{
id: 1,
name: "国产红富士苹果(5斤装)",
price: 19.9,
quantity: 1,
isChecked: false,
imgUrl: "https://via.placeholder.com/80" // 用占位图代替真实图片
},
{
id: 2,
name: "云南阳光玫瑰葡萄(2斤装)",
price: 39.8,
quantity: 1,
isChecked: false,
imgUrl: "https://via.placeholder.com/80"
},
{
id: 3,
name: "新疆库尔勒香梨(3斤装)",
price: 25.8,
quantity: 1,
isChecked: false,
imgUrl: "https://via.placeholder.com/80"
}
];
每个商品对象里的字段,对应之前表格里的“核心功能”——比如id
用来唯一标识商品(删商品时要用),isChecked
表示是否选中(计算总价时要用)。
写一个renderCart
函数,用来把cartData
里的数据变成HTML,插入到
里。我用模板字符串(反引号)来拼HTML,比之前用字符串相加方便多了:
function renderCart() {
).join(''); // 把数组变成字符串const cartList = document.querySelector('.cart-list');
// 用map遍历数据,生成每个商品项的HTML
const html = cartData.map(item =>
<!-
勾选框 > <!-
商品图片 >
<!-
商品信息 > ${item.name}
¥${item.price.toFixed(2)}
<!-保留两位小数 > <!-
数量控制 >
<!-
删除按钮 >
cartList.innerHTML = html; // 插入到商品列表容器
}
这里有个小技巧:给每个商品项加data-id="${item.id}"
——后面点击删除或改数量时,能通过这个data-id
找到对应的商品数据。比如用户点“删除”按钮,我可以用e.target.closest('.cart-item').dataset.id
拿到商品id,再从cartData
里找到对应的商品删掉。
事件绑定是购物车的“交互核心”,我会写几个函数,分别处理数量增减、勾选、删除的事件:
(1)数量增减事件——修改数量并重新渲染
给“+/-”按钮绑定点击事件,逻辑是:
quantity
(减的时候不能小于1); function bindQuantityEvents() {
// 找所有“减”按钮
const minusBtns = document.querySelectorAll('.minus');
minusBtns.forEach(btn => {
btn.addEventListener('click', e => {
// 找到当前商品项的id
const itemId = e.target.closest('.cart-item').dataset.id;
// 找到对应的商品数据
const item = cartData.find(i => i.id === parseInt(itemId));
// 数量不能小于1
if (item.quantity > 1) {
item.quantity;
renderCart(); // 重新渲染购物车
calculateTotal(); // 重新计算总价
bindQuantityEvents(); // 重新绑定事件(因为渲染后按钮被替换了)
bindDeleteEvents(); // 同理,删除按钮也要重新绑定
}
});
});
// “加”按钮的逻辑,和减类似
const plusBtns = document.querySelectorAll('.plus');
plusBtns.forEach(btn => {
btn.addEventListener('click', e => {
const itemId = e.target.closest('.cart-item').dataset.id;
const item = cartData.find(i => i.id === parseInt(itemId));
item.quantity++;
renderCart();
calculateTotal();
bindQuantityEvents();
bindDeleteEvents();
});
});
}
注意:重新渲染后,原来的按钮被替换了,所以要重新绑定事件——新手容易漏这一步,导致“点击第二次没反应”的bug。我当初帮朋友调的时候,就因为漏了bindQuantityEvents()
,结果用户点“+”号只能加一次,第二次就没反应了。
(2)勾选事件——联动选中状态和总价
给勾选框绑定change
事件,修改isChecked
字段,然后重新计算总价:
function bindCheckEvents() {
const checkboxes = document.querySelectorAll('.item-check');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', e => {
const itemId = e.target.closest('.cart-item').dataset.id;
const item = cartData.find(i => i.id === parseInt(itemId));
item.isChecked = e.target.checked; // 修改选中状态
calculateTotal(); // 重新计算总价
});
});
}
(3)删除事件——删掉商品并重新渲染
给删除按钮绑定点击事件,逻辑是:
cartData
里过滤掉对应的商品; function bindDeleteEvents() {
const deleteBtns = document.querySelectorAll('.item-delete');
deleteBtns.forEach(btn => {
btn.addEventListener('click', e => {
const itemId = e.target.closest('.cart-item').dataset.id;
// 过滤掉要删除的商品(保留id不等于当前id的商品)
cartData = cartData.filter(item => item.id !== parseInt(itemId));
renderCart(); // 重新渲染
calculateTotal(); // 重新计算总价
bindQuantityEvents(); // 重新绑定数量事件
});
});
}
本文常见问题(FAQ)
购物车界面必须实现的核心功能有哪些?
购物车的核心功能主要有5个:一是商品列表展示,得清晰显示商品图片、名称、单价;二是数量增减,支持“+/-”按钮和输入框修改,且数量不能小于1;三是总价实时计算,选商品或改数量后总价要立刻更新;四是选中状态联动,勾选或取消勾选商品时,总价要对应变化;五是删除商品,用户能删掉不想买的商品。这些功能是实际项目里用户最在意的,比如之前帮朋友做社区团购站,漏了总价实时计算,被用户骂“诈骗”,补全后才解决问题。
什么是“数据驱动界面”?为什么做购物车要重视这个逻辑?
“数据驱动界面”就是做操作时先修改背后的数据,再根据数据重新渲染界面。比如用户点“+”号,不是直接改输入框的value,而是先找到cartData里对应商品的quantity并加1,再重新调用renderCart函数更新界面。之前帮朋友做的时候,一开始直接改DOM,结果数量涨了但总价没变——因为数据没同步,后来换成“数据驱动”,界面和数据就一致了,再也没出现过这种bug。
写购物车的JS逻辑时,为什么要分模块?
分模块写JS主要是方便维护和找bug。比如把逻辑分成数据初始化、渲染商品、绑定事件、计算总价这几个模块,后期如果数量增减的逻辑出问题,直接找bindQuantityEvents函数就行,不用在一堆代码里翻。之前我犯过堆代码的错,改数量的bug花了2小时,分模块后只花10分钟就找到了问题。
跟着这个教程做的购物车,能直接用到实际小项目里吗?
完全可以!这个购物车包含了社区团购、美妆小店、水果电商等小项目常用的核心功能,比如数量限制、总价实时联动、选中状态管理、删除商品。只要把教程里的模拟数据(cartData)换成后端接口返回的数据,就能直接用在项目里——我去年帮朋友的社区团购站就用了这个逻辑,用户反馈比之前的购物车好用多了。
搭购物车的HTML结构时,为什么要越简洁越好?
简洁的HTML结构更容易维护和修改。比如用语义化标签(ul放商品列表、li放单个商品),加明确的类名(.cart-item代表商品项、.item-check代表勾选框),后期想改商品图片的大小,直接找.item-img类就行;如果结构复杂,用了很多div嵌套,改起来得找半天元素。之前我用复杂结构搭购物车,改商品名称的位置花了半小时,现在用简洁结构10分钟就搞定了。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
站长QQ:709466365 站长邮箱:709466365@qq.com