手把手教你用JS编写购物车界面:新手一看就会的完整实战教程

文章目录CloseOpen

    • 先理清楚:购物车界面到底要实现哪些核心功能?
    • 手把手写代码:从0到1实现能落地的购物车
      • 第一步:搭HTML结构——越简洁越好
      • 我的购物车
      • 第二步:写CSS基础样式——先保证功能能用
      • 第三步:写JS逻辑——分模块,别堆在一起
    • 本文常见问题(FAQ)
      • 购物车界面必须实现的核心功能有哪些?
      • 什么是“数据驱动界面”?为什么做购物车要重视这个逻辑?
      • 写购物车的JS逻辑时,为什么要分模块?
      • 跟着这个教程做的购物车,能直接用到实际小项目里吗?
      • 搭购物车的HTML结构时,为什么要越简洁越好?

    我们从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,核心是“购物车容器”和“商品项模板”。我一般会用语义化标签,比如用

      放商品列表,

    • 放单个商品,这样搜索引擎和屏幕阅读器都能识别:

      我的购物车

        <!-
      • 商品列表容器 >
      • 合计:

        ¥0.00

        然后,每个商品项的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 =>

      • <!-

      • 勾选框 >
      • <!-

      • 商品图片 >
      • <!-

      • 商品信息 >
      • ${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分钟就搞定了。

      • 温馨提示:本站提供的一切软件、教程和内容信息都来自网络收集整理,仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,版权争议与本站无关。用户必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。如果您喜欢该程序和内容,请支持正版,购买注册,得到更好的正版服务。我们非常重视版权问题,如有侵权请邮件与我们联系处理。敬请谅解! 联系邮箱:lgg.sinyi@qq.com

        给TA打赏
        共{{data.count}}人
        人已打赏
        行业资讯

        付费直播源码怎么选?高转化的核心功能与避坑指南

        2025-9-17 19:25:36

        行业资讯

        PixiJS网页游戏性能优化指南:告别卡顿与低帧率的实战技巧

        2025-9-17 19:25:45

        0 条回复 A文章作者 M管理员
          暂无讨论,说说你的看法吧
        个人中心
        购物车
        优惠劵
        今日签到
        有新私信 私信列表
        搜索