游侠网云服务,免实名免备案服务器 游侠云域名,免实名免备案域名

统一声明:

1.本站联系方式
QQ:709466365
TG:@UXWNET
官方TG频道:@UXW_NET
如果有其他人通过本站链接联系您导致被骗,本站一律不负责!

2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET
3.免实名域名注册购买- 游侠云域名
4.免实名国外服务器购买- 游侠网云服务
手把手教你用JS编写购物车界面:新手一看就会的完整实战教程

我们从0到1,手把手教你实现一个完整的购物车:先搭好HTML结构和基础样式,再一步步写JS逻辑——商品怎么动态渲染?数量增减怎么联动数据?总价怎么实时更新?选中商品怎么统计?每一步都有详细代码+通俗讲解,没有复杂黑科技,新手跟着敲就能懂。更重要的是,这个购物车不是“玩具”——它包含了实际项目里常用的核心功能,做完就能直接用到你的小项目里。

不管你是刚学JS的新手,还是想补全实战能力的学习者,跟着这篇教程走,保证你能亲手做出一个能落地的购物车,把“纸上的JS知识”变成“能跑的交互功能”,成就感直接拉满!

你有没有过这种情况?学JS的时候跟着教程做购物车,要么代码copy过来能跑但根本不懂逻辑,要么做完只有个空架子,连数量增减都不联动总价?我去年帮朋友的社区团购小站做购物车时,就遇到过这问题——他找了个教程跟着做,结果用户点“+”号,数量涨了但总价没变,反馈全是骂人的。后来我帮他重构了一遍,把“数据驱动界面”的逻辑理清楚,才解决了问题。今天我就把当时的步骤拆解给你,不用懂复杂的框架,纯JS就能做,做完直接能用在小项目里。

先理清楚:购物车界面到底要实现哪些核心功能?

很多新手刚学的时候,总想着“做个好看的界面”,但实际项目里,功能的合理性比样式重要10倍。我帮朋友做的时候,一开始没明确核心功能,导致做了很多无用功——比如先加了商品分类筛选,结果用户根本用不上,反而把购物车搞得很复杂。后来我查了几个小电商站的购物车,又问了做前端的朋友,才 出购物车的5个必做核心功能

  • 商品列表展示:得清晰显示商品图片、名称、单价——别嫌麻烦,我之前漏了商品图片,朋友说用户看不到图就没购买欲;
  • 数量增减:支持“+/-”按钮和输入框修改数量,且数量不能小于1——之前帮另一个做美妆小店的朋友调bug,就是因为没加“最小1”的限制,用户把数量改成0,导致总价负数;
  • 总价实时计算:选了的商品、改了数量后,总价要立刻变——这是用户最在意的,我朋友之前就是漏了这个,被用户骂“诈骗”;
  • 选中状态联动:勾选商品后,总价要包含它;取消勾选,总价要去掉——别像我之前那样,把选中和总价分开,结果逻辑混乱;
  • 删除商品:用户不想买了能删掉——这个功能看似简单,但要注意删除后要重新渲染列表和计算总价。
  • 为了让你更清楚“功能和数据的对应关系”,我做了张表格——你看,每个功能都对应着具体的数据字段,后面写代码时直接“对号入座”就行:

    核心功能 对应数据字段 用户操作场景
    商品展示 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() {
    

    const cartList = document.querySelector('.cart-list');

    // 用map遍历数据,生成每个商品项的HTML

    const html = cartData.map(item =>

  • <!-

  • 勾选框 >
  • <!-

  • 商品图片 >
  • 手把手教你用JS编写购物车界面:新手一看就会的完整实战教程 二

    <!-

  • 商品信息 >
  • ${item.name}

    ¥${item.price.toFixed(2)}

    <!-
  • 保留两位小数 >
  • <!-

  • 数量控制 >
  • <!-

  • 删除按钮 >
  • ).join(''); // 把数组变成字符串

    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)删除事件——删掉商品并重新渲染

    给删除按钮绑定点击事件,逻辑是:

  • 找到商品id;
  • 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分钟就搞定了。