更新记录

1.0.0(2026-06-05)

  • ✅ 商品列表展示(图片、名称、规格、单价、数量)
  • ✅ 数量增减控制(支持按钮点击和输入框输入)
  • ✅ 库存限制(数量不会超过库存上限)
  • ✅ 单选/全选功能(支持单个商品选中和全选/反选)
  • ✅ 实时价格计算(根据选中商品实时计算总价)
  • ✅ 空状态提示(购物车为空时显示引导图和按钮)
  • ✅ 结算跳转(点击结算将选中商品传递给订单确认页)
  • ✅ 单商品模式(商品平铺展示,适用于单一商家场景)
  • ✅ 多商家模式(商品按商家分组展示,支持商家级别的全选)
  • ✅ 自定义样式配置(所有样式均可通过配置参数自定义)
  • ✅ 底部安全区域适配(支持 tabbar 页面和非 tabbar 页面)

平台兼容性

uni-app(3.7.8)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
-
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - -

其他

多语言 暗黑模式 宽屏模式
× ×

Shop-Cart 购物车组件

基于 uni-app 框架开发的购物车组件,支持单商品模式和多商家模式两种展示方式,提供完整的购物车功能和丰富的自定义配置选项。


特性

功能 说明 状态
商品列表展示 支持商品图片、名称、规格、单价、数量的完整展示
数量增减控制 支持点击按钮增减和输入框直接输入两种方式
库存限制 可设置库存上限,数量不会超过库存
单选/全选 支持单个商品选中切换和全选/反选功能
实时价格计算 根据选中商品实时计算总价和选中数量
空状态提示 购物车为空时显示引导图和"去逛逛"按钮
结算跳转 点击结算将选中商品传递给订单确认页
商品点击 支持点击商品跳转到详情页
商家点击 支持点击商家跳转到店铺页(仅多商家模式)
单商品模式 商品平铺展示,适用于单一商家场景
多商家模式 商品按商家分组展示,支持商家级别的全选
自定义样式 所有样式均可通过配置参数自定义
安全区域适配 支持底部安全区域自动适配

组件结构

shop-cart/
├── package.json            # 组件元信息
├── README.md               # 组件文档
├── shop-cart.vue          # 主组件,控制整体逻辑和布局
├── shop-cart-item.vue     # 商品项组件,展示单个商品
├── shop-cart-group.vue    # 商家分组组件,多商家模式下使用
├── shop-cart-footer.vue   # 底部结算栏,包含全选和结算按钮
├── shop-cart-empty.vue    # 空状态组件,购物车为空时显示
└── quantity-control.vue   # 数量控制器组件,独立封装复用

安装与使用

环境要求

  • uni-app 框架
  • Vue 2.x 或 Vue 3.x
  • SCSS 支持

安装方式

  1. 复制组件:将 shop-cart 文件夹复制到项目的 components 目录下

  2. easycom 配置:确保 pages.json 中配置了 easycom 自动引入:

{
  "easycom": {
    "autoscan": true,
    "custom": {
      "^shop-cart(.*)": "@/components/shop-cart/shop-cart$1.vue"
    }
  }
}
  1. 静态资源:将 static 目录下的图标文件复制到项目的 static 目录

使用示例

基础用法 - 单商品模式

<template>
  <view class="page-container">
    <shop-cart 
      :cart-list="cartList" 
      mode="single"
      :config="cartConfig"
      @update="handleCartUpdate" 
      @go-shopping="goShopping" 
      @checkout="handleCheckout"
      @click="handleItemClick"
    />
  </view>
</template>

<script>
export default {
  name: 'SingleCartPage',
  data() {
    return {
      // 购物车商品列表
      cartList: [
        {
          id: 1,
          name: 'iPhone 15 Pro Max 256GB',
          spec: '原色钛金属',
          price: 9999,
          quantity: 1,
          stock: 10,
          selected: true,
          image: 'https://picsum.photos/160/160?random=1'
        },
        {
          id: 2,
          name: 'MacBook Pro 14英寸',
          spec: 'M3 Pro芯片 18GB内存 512GB',
          price: 16999,
          quantity: 2,
          stock: 5,
          selected: false,
          image: 'https://picsum.photos/160/160?random=2'
        }
      ],
      // 配置对象
      cartConfig: {
        safeArea: true,
        containerBg: '#f5f5f5',
        empty: {
          text: '购物车空空如也',
          btnText: '去逛逛',
          btnBg: '#1677FF',
          btnColor: '#fff'
        },
        item: {
          bg: '#fff',
          borderRadius: '16rpx',
          nameColor: '#333',
          specColor: '#999',
          priceColor: '#1677FF',
          checkedIcon: '/static/icon-check-s.png',
          uncheckedIcon: '/static/icon-check-n.png',
          qty: {
            bg: '#f5f5f5',
            btnColor: '#1677FF',
            valueColor: '#333'
          }
        },
        footer: {
          selectedText: '已选',
          unitText: '件',
          checkoutText: '结算',
          bg: '#fff',
          selectedCountColor: '#1677FF',
          priceValueColor: '#1677FF',
          checkoutBtnBg: '#1677FF',
          checkoutBtnColor: '#fff',
          checkoutBtnDisabledBg: '#ccc'
        }
      }
    }
  },
  methods: {
    /**
     * 购物车数据更新回调
     * @param {Array} newList - 更新后的购物车列表
     */
    handleCartUpdate(newList) {
      this.cartList = newList
      uni.setStorageSync('cartList', JSON.stringify(this.cartList))
    },

    /**
     * 点击"去逛逛"按钮
     */
    goShopping() {
      uni.switchTab({
        url: '/pages/index/index'
      })
    },

    /**
     * 点击商品项,跳转到商品详情页
     * @param {Object} item - 商品对象
     */
    handleItemClick(item) {
      uni.navigateTo({
        url: `/pages/product-detail/index?id=${item.id}`
      })
    },

    /**
     * 点击结算按钮
     * @param {Array} selectedItems - 选中的商品列表
     */
    handleCheckout(selectedItems) {
      uni.setStorageSync('selectedItems', JSON.stringify(selectedItems))
      uni.navigateTo({
        url: '/pages/checkout/index'
      })
    }
  },
  onLoad() {
    const savedCart = uni.getStorageSync('cartList')
    if (savedCart) {
      this.cartList = JSON.parse(savedCart)
    }
  }
}
</script>

<style lang="scss">
.page-container {
  min-height: 100vh;
  background: #f5f5f5;
}
</style>

基础用法 - 多商家模式

<template>
  <view class="page-container">
    <shop-cart 
      :cart-list="groupCartList" 
      mode="group"
      :config="cartConfig"
      @update="handleCartUpdate" 
      @go-shopping="goShopping" 
      @checkout="handleCheckout"
      @click="handleItemClick"
      @group-click="handleGroupClick"
    />
  </view>
</template>

<script>
export default {
  name: 'GroupCartPage',
  data() {
    return {
      // 多商家购物车列表
      groupCartList: [
        {
          id: 'group1',
          name: 'Apple Store',
          shopName: '官方旗舰店',
          items: [
            {
              id: 1,
              name: 'iPhone 15 Pro',
              spec: '128GB 蓝色钛金属',
              price: 7999,
              quantity: 1,
              stock: 20,
              selected: true,
              image: 'https://picsum.photos/160/160?random=1'
            },
            {
              id: 2,
              name: 'AirPods Pro 2',
              spec: '第二代 USB-C充电盒',
              price: 1899,
              quantity: 2,
              stock: 50,
              selected: false,
              image: 'https://picsum.photos/160/160?random=2'
            }
          ]
        },
        {
          id: 'group2',
          name: '数码配件馆',
          shopName: '精选配件',
          items: [
            {
              id: 3,
              name: 'MagSafe充电器',
              spec: '15W无线快充',
              price: 329,
              quantity: 1,
              stock: 100,
              selected: true,
              image: 'https://picsum.photos/160/160?random=3'
            }
          ]
        }
      ],
      cartConfig: {
        safeArea: false,
        containerBg: '#f8f8f8',
        empty: {
          text: '购物车空空如也',
          btnText: '去逛逛',
          btnBg: '#ff6b6b',
          btnColor: '#fff'
        },
        item: {
          bg: '#fff',
          borderRadius: '12rpx',
          nameColor: '#1a1a1a',
          specColor: '#999',
          priceColor: '#ff6b6b',
          checkedIcon: '/static/icon-check-s.png',
          uncheckedIcon: '/static/icon-check-n.png',
          qty: {
            bg: '#f0f0f0',
            btnColor: '#666',
            valueColor: '#333'
          }
        },
        footer: {
          selectedText: '已选',
          unitText: '件',
          checkoutText: '结算',
          bg: '#fff',
          selectedCountColor: '#ff6b6b',
          priceValueColor: '#ff6b6b',
          checkoutBtnBg: '#ff6b6b',
          checkoutBtnColor: '#fff',
          checkoutBtnDisabledBg: '#ccc'
        }
      }
    }
  },
  methods: {
    handleCartUpdate(newList) {
      this.groupCartList = newList
      uni.setStorageSync('groupCartList', JSON.stringify(this.groupCartList))
    },
    goShopping() {
      uni.showToast({
        title: '跳转到商品列表',
        icon: 'none'
      })
    },
    /**
     * 点击商品项,跳转到商品详情页
     * @param {Object} item - 商品对象
     */
    handleItemClick(item) {
      uni.navigateTo({
        url: `/pages/product-detail/index?id=${item.id}`
      })
    },
    /**
     * 点击商家头部,跳转到店铺页面
     * @param {Object} group - 商家分组对象
     */
    handleGroupClick(group) {
      uni.navigateTo({
        url: `/pages/shop-detail/index?id=${group.id}`
      })
    },
    handleCheckout(selectedItems) {
      const totalPrice = selectedItems.reduce((sum, item) => {
        return sum + item.price * item.quantity
      }, 0)
      uni.showModal({
        title: '确认结算',
        content: `共 ${selectedItems.length} 种商品,合计 ¥${totalPrice.toFixed(2)}`,
        confirmText: '去支付',
        success: (res) => {
          if (res.confirm) {
            uni.setStorageSync('selectedItems', JSON.stringify(selectedItems))
            uni.navigateTo({
              url: '/pages/checkout/index'
            })
          }
        }
      })
    }
  },
  onLoad() {
    const savedCart = uni.getStorageSync('groupCartList')
    if (savedCart) {
      this.groupCartList = JSON.parse(savedCart)
    }
  }
}
</script>

API 文档

Props

参数 类型 默认值 必填 说明
cartList Array [] 购物车商品列表,根据 mode 不同有不同的数据结构
mode String 'single' 展示模式:'single' 单商品模式,'group' 多商家模式
config Object {} 配置对象,用于自定义样式和文案

Config 配置项详解

顶层配置

属性 类型 默认值 说明
safeArea Boolean true 是否需要底部安全区域,非 tabbar 页面设置为 true,tabbar 页面设置为 false
containerBg String '#f8f8f8' 购物车容器的背景色

empty - 空状态配置

属性 类型 默认值 说明
empty.text String '购物车空空如也' 空状态提示文字
empty.btnText String '去逛逛' 空状态按钮文字
empty.btnBg String '#1677FF' 空状态按钮背景色
empty.btnColor String '#fff' 空状态按钮文字颜色

item - 商品项配置

属性 类型 默认值 说明
item.bg String '#fff' 商品项背景色
item.borderRadius String '16rpx' 商品项圆角大小
item.nameColor String '#333' 商品名称颜色
item.specColor String '#999' 商品规格颜色
item.priceColor String '#1677FF' 商品价格颜色
item.checkedIcon String '/static/icon-check-s.png' 选中状态图标路径
item.uncheckedIcon String '/static/icon-check-n.png' 未选中状态图标路径

item.qty - 数量控制器配置

属性 类型 默认值 说明
item.qty.bg String '#f5f5f5' 数量控制器背景色
item.qty.btnColor String '#1677FF' 增减按钮颜色
item.qty.valueColor String '#333' 数量数值颜色

footer - 底部结算栏配置

属性 类型 默认值 说明
footer.selectedText String '已选' 已选文字
footer.unitText String '件' 单位文字
footer.checkoutText String '结算' 结算按钮文字
footer.bg String '#fff' 底部栏背景色
footer.selectedCountColor String '#1677FF' 选中数量颜色
footer.priceLabel String '合计:' 价格标签文字
footer.priceLabelColor String '#666' 价格标签颜色
footer.priceValueColor String '#1677FF' 总价数值颜色
footer.checkoutBtnBg String '#1677FF' 结算按钮背景色
footer.checkoutBtnColor String '#fff' 结算按钮文字颜色
footer.checkoutBtnDisabledBg String '#ccc' 结算按钮禁用状态背景色

Events

事件名 参数 说明
update cartList (Array) 购物车数据更新时触发,携带更新后的完整购物车列表
go-shopping - 点击空状态的"去逛逛"按钮时触发
checkout selectedItems (Array) 点击结算按钮时触发,携带选中的商品列表
click item (Object) 点击商品项时触发,携带商品对象(用于跳转详情页)
group-click group (Object) 点击商家头部时触发,携带分组对象(用于跳转店铺页,仅多商家模式)

数据结构

单商品模式 cartList

[
  {
    id: 1,                    // 商品唯一ID,Number 或 String
    name: '商品名称',           // 商品名称,必填
    spec: '规格描述',           // 商品规格,如颜色、尺寸等,必填
    price: 99.99,             // 商品单价,Number,必填
    quantity: 1,              // 购买数量,Number,默认1
    stock: 10,                // 库存数量,Number,默认999
    selected: true,           // 是否选中,Boolean,默认false
    image: 'https://...'      // 商品图片地址,必填
  }
]

多商家模式 cartList

[
  {
    id: 'group1',             // 商家分组ID,String
    name: '商家名称',           // 商家名称,必填
    shopName: '店铺名称',       // 店铺名称,选填
    items: [
      {
        id: 1,                // 商品唯一ID
        name: '商品名称',       // 商品名称
        spec: '规格描述',       // 商品规格
        price: 99.99,         // 商品单价
        quantity: 1,          // 购买数量
        stock: 10,            // 库存数量
        selected: true,       // 是否选中
        image: 'https://...'  // 商品图片地址
      }
    ]
  }
]

子组件说明

1. shop-cart-item(商品项组件)

Props 属性 类型 默认值 说明
item Object - 商品对象(必填)
config Object {} 配置对象
mode String 'group' 展示模式
Events 事件名 参数 说明
select id 点击复选框时触发
increase item 数量增加时触发
decrease item 数量减少时触发
update (item, val) 数量直接输入更新时触发
click item 点击商品内容区域时触发(跳转详情页)

2. shop-cart-group(商家分组组件)

Props 属性 类型 默认值 说明
group Object - 商家分组对象(必填)
config Object {} 配置对象
Events 事件名 参数 说明
update group 分组内数据更新时触发
click item 点击商品项时触发
group-click group 点击商家头部时触发(跳转店铺页)

3. shop-cart-footer(底部结算栏组件)

Props 属性 类型 默认值 说明
selectedCount Number 0 选中的商品种类数
totalPrice Number 0 选中商品的总价
isAllSelected Boolean false 是否全选
config Object {} 配置对象
safeArea Boolean true 是否需要底部安全区域
Events 事件名 参数 说明
checkout - 点击结算按钮时触发
select-all - 点击全选按钮时触发

4. shop-cart-empty(空状态组件)

Props 属性 类型 默认值 说明
config Object {} 配置对象
Events 事件名 参数 说明
click - 点击按钮时触发

5. quantity-control(数量控制器组件)

Props 属性 类型 默认值 说明
quantity Number 1 当前数量
stock Number 999 库存上限
config Object {} 配置对象
Events 事件名 参数 说明
decrease - 数量减少时触发
increase - 数量增加时触发
update val 数量直接输入更新时触发

自定义样式示例

示例1:自定义主题色

cartConfig: {
  containerBg: '#f0f4f8',
  item: {
    priceColor: '#FF5252',
    qty: {
      btnColor: '#FF5252'
    }
  },
  footer: {
    selectedCountColor: '#FF5252',
    priceValueColor: '#FF5252',
    checkoutBtnBg: '#FF5252'
  }
}

示例2:自定义图标

cartConfig: {
  item: {
    checkedIcon: '/static/icons/checked.png',
    uncheckedIcon: '/static/icons/unchecked.png'
  },
  footer: {
    checkedIcon: '/static/icons/checked.png',
    uncheckedIcon: '/static/icons/unchecked.png'
  }
}

示例3:调整尺寸

cartConfig: {
  item: {
    borderRadius: '8rpx',
    qty: {
      bg: '#fafafa',
      btnColor: '#333',
      valueColor: '#1a1a1a'
    }
  }
}

注意事项

  1. 图片尺寸:商品图片建议使用 160x160 像素,以获得最佳显示效果

  2. 安全区域适配

    • 如果购物车页面是 tabbar 页面,设置 safeArea: false
    • 如果购物车页面是普通页面(非 tabbar),设置 safeArea: true
  3. 数据持久化:建议在 @update 事件中保存购物车数据到本地存储

  4. 空状态图标:默认使用网络图片,如需自定义请替换 empty.icon 配置

  5. 图标路径:复选框图标默认使用 /static/icon-check-s.png/static/icon-check-n.png,请确保这些文件存在

  6. 数量限制:数量最小为 1,最大为 stock 值(默认 999)

  7. 点击事件

    • @click 事件在单商品模式和多商家模式下都会触发
    • @group-click 事件仅在多商家模式下触发

更新日志

v1.1.0

新增功能

  • ✅ 商品点击事件(@click),支持跳转商品详情页
  • ✅ 商家点击事件(@group-click),支持跳转店铺页面(仅多商家模式)
  • ✅ 优化商品项布局,支持点击区域精确控制

更新文档

  • 更新 README.md,添加新事件说明和示例

v1.0.0

新增功能

  • ✅ 商品列表展示(图片、名称、规格、单价、数量)
  • ✅ 数量增减控制(支持输入)
  • ✅ 单选/全选功能
  • ✅ 实时价格计算
  • ✅ 空状态提示
  • ✅ 结算跳转
  • ✅ 单商品模式
  • ✅ 多商家模式
  • ✅ 自定义样式配置
  • ✅ 底部安全区域适配

组件文件

  • shop-cart.vue - 主组件
  • shop-cart-item.vue - 商品项组件
  • shop-cart-group.vue - 商家分组组件
  • shop-cart-footer.vue - 底部结算栏
  • shop-cart-empty.vue - 空状态组件
  • quantity-control.vue - 数量控制器

配置文件

  • package.json - 组件元信息
  • README.md - 组件文档

License

MIT License


作者

如有问题或建议,欢迎反馈。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。