【愚公系列】2022年10月 微信小程序-电商项目-商品购物车功能实现

举报
愚公搬代码 发表于 2022/10/31 19:24:49 2022/10/31
【摘要】 前言在电商的核心交易流程中,购物车是其中非常重要的一环,它承担商品加购、价格计算、促销活动展示等功能,与会员系统、商品系统、库存系统、订单系统等紧密结合。vant-weapp的GoodsAction商品导航apiGoodsAction Props参数说明类型默认值safe-area-inset-bottom是否为 iPhoneX 留出底部安全距离booleantrueGoodsAction...

前言

在电商的核心交易流程中,购物车是其中非常重要的一环,它承担商品加购、价格计算、促销活动展示等功能,与会员系统、商品系统、库存系统、订单系统等紧密结合。

vant-weapp的GoodsAction商品导航api

GoodsAction Props

参数 说明 类型 默认值
safe-area-inset-bottom 是否为 iPhoneX 留出底部安全距离 boolean true

GoodsActionIcon Props

参数 说明 类型 默认值
text 按钮文字 string -
icon 图标类型,可选值见icon组件 string -
info 图标右上角提示信息 string/number -
url 点击后跳转的链接地址 string -
link-type 链接跳转类型,可选值为 redirectTo switchTab reLaunch string navigateTo
id 标识符 string -
disabled 是否禁用按钮 boolean false
loading 是否显示为加载状态 boolean false
open-type 微信开放能力,具体支持可参考 微信官方文档 string -
app-parameter 打开 APP 时,向 APP 传递的参数 string -
lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 string en
session-from 会话来源 string -
send-message-title 会话内消息卡片标题 string 当前标题
send-message-path 会话内消息卡片点击跳转小程序路径 string 当前分享路径
send-message-img sendMessageImg string 截图
show-message-card 显示会话内消息卡片 string false
class-prefix v1.10.1 类名前缀 string van-icon

GoodsActionButton Props

参数 说明 类型 默认值
text 按钮文字 string -
color 按钮颜色,支持传入 linear-gradient 渐变色 string -
url 点击后跳转的链接地址 string -
link-type 链接跳转类型,可选值为 redirectTo switchTab reLaunch string navigateTo
id 标识符 string -
type 按钮类型,可选值为 primary warning danger string danger
plain 是否为朴素按钮 boolean false
size 按钮尺寸,可选值为 normal large small mini string normal
disabled 是否禁用按钮 boolean false
loading 是否显示为加载状态 boolean false
open-type 微信开放能力,具体支持可参考 微信官方文档 string -
app-parameter 打开 APP 时,向 APP 传递的参数 string -
lang 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文 string en
session-from 会话来源 string -
send-message-title 会话内消息卡片标题 string 当前标题
send-message-path 会话内消息卡片点击跳转小程序路径 string 当前分享路径
send-message-img sendMessageImg string 截图
show-message-card 显示会话内消息卡片 string false

Events

事件名 说明 参数
bind:click 按钮点击事件回调 -

GoodsActionIcon Slot

名称 说明
icon 自定义图标

GoodsActionButton Slot

名称 说明
/ 按钮显示内容

GoodsActionIcon 外部样式类

类名 说明
icon-class 图标样式类
text-class 文字样式类

GoodsActionButton 外部样式类

类名 说明
custom-class 根节点样式类

一、商品购物车功能实现

// miniprogram/pages/cart/index.js

Page({
  /**
   * 页面的初始数据
   */
  data: {
    showLoginPanel:false,
    cartIdSelectedResult:[],
    allIsSelected:false,
    editMode:false,
    carts:[],
    totalPrice:0
  },
  // 重新计算总价
  calcTotalPrice(){
    let totalPrice = 0
    let ids = this.data.cartIdSelectedResult
    let carts = this.data.carts
    ids.forEach(id=>{
      carts.some(item=>{
        if (item.id == id){
          totalPrice += item.price * item.num 
          return true 
        }
        return false
      })
    })
    this.setData({
      totalPrice
    })
  },
  //改变编辑模式
  changeEditMode(){
    let editMode = !this.data.editMode
    this.setData({
      editMode
    })
  },

  onSelectGoodsItem(e){
    let cartIdSelectedResult = e.detail
    this.setData({
      cartIdSelectedResult,
    });
    this.calcTotalPrice()
  },
  onSelectAll(event) {
    let allIsSelected = event.detail
    let cartIdSelectedResult = this.data.cartIdSelectedResult
    cartIdSelectedResult.length = 0

    if (allIsSelected){
      let carts = this.data.carts
      for(let j=0;j<carts.length;j++){
        cartIdSelectedResult.push(`${carts[j].id}`)
      }
    }

    this.setData({
      allIsSelected,
      cartIdSelectedResult
    });
    this.calcTotalPrice()
  },

  /**
   * 页面显示的时候去加载数据
   */
  async onShow(){
    let res = await getApp().wxp.request4({
      url:'http://localhost:3000/user/my/carts',
      method:'get'
    })
    if (res.data.msg == "ok"){
      let carts = res.data.data 
      this.setData({
        carts
      })
    }
  },

  onCartConfirm(e){
    // 拿到列表数据
    let carts = this.data.carts 
    let cartData = []
    let ids = this.data.cartIdSelectedResult
    if (ids.length == 0){
      wx.showModal({
        title: '未选择商品',
        showCancel: false
      })
      return
    }
    ids.forEach(id=>{
      carts.some(item=>{
        if (item.id == id){
          cartData.push(Object.assign({}, item))
          return true 
        }
        return false
      })
    })
    wx.navigateTo({
      url: `/pages/confirm-order/index`,
      success: function(res) {
        res.eventChannel.emit('cartData', { data: cartData })
      }
    })
  },

  async onCartGoodsNumChanged(e){
    let cartGoodsId = e.currentTarget.dataset.id 
    let oldNum = parseInt( e.currentTarget.dataset.num )
    // console.log('e.detail', typeof e.detail, cartGoodsId, oldNum)
    let num = e.detail
    let data = {num}

    let res = await getApp().wxp.request4({
      url:`http://localhost:3000/user/my/carts/${cartGoodsId}`,
      method:'put',
      data 
    })
    if (res.data.msg == 'ok'){
      wx.showToast({
        title: num > oldNum ? '增加成功' : '减少成功',
      })
      // 修复数据
      let carts = this.data.carts
      carts.some(item=>{
        if (item.id == cartGoodsId){
          item.num = num 
          return true 
        }
        return false
      })
      this.calcTotalPrice()
    }
  },

  async removeCartGoods(e){
    let ids = this.data.cartIdSelectedResult
    if (ids.length == 0){
      wx.showModal({
        title: '没有选择商品',
        showCancel: false
      })
      return 
    }
    let data = {ids}
    let res = await getApp().wxp.request4({
      url:'http://localhost:3000/user/my/carts',
      method:'delete',
      data
    })
    if (res.data.msg == 'ok'){
      let carts = this.data.carts
      for(let j=0;j<ids.length;j++){
        let id = ids[j]
        carts.some((item,index)=>{
          if (item.id == id){
            carts.splice(index,1)
            return true 
          }
          return false 
        })
      }
      this.setData({
        carts
      })
    }
  },
})
{
  "usingComponents": {
    "van-cell": "@vant/weapp/cell/index",
    "van-cell-group": "@vant/weapp/cell-group/index",
    "van-button": "@vant/weapp/button/index",
    "van-card": "@vant/weapp/card/index",
    "van-stepper": "@vant/weapp/stepper/index",
    "van-submit-bar": "@vant/weapp/submit-bar/index",
    "van-checkbox": "@vant/weapp/checkbox/index",
    "van-checkbox-group": "@vant/weapp/checkbox-group/index",
    "LoginPanel": "../../components/login"
  }
}
<!--miniprogram/pages/cart/index.wxml-->
<!-- <text>miniprogram/pages/cart/index.wxml</text> -->

<van-cell-group>
	<van-cell title="购物车" value="" label="" border="{{ false }}">
		<van-button bindtap="changeEditMode" slot="right-icon" plain type="info" size="mini">{{editMode?'完成':'编辑'}}</van-button>
	</van-cell>
</van-cell-group>

<block wx:for="{{carts}}" wx:key="id">
<van-checkbox-group value="{{ cartIdSelectedResult }}" bind:change="onSelectGoodsItem">
	<view class="goods-card-container">
		<view style="width:30px;display:flex;align-items:center;justify-content:center;">
			<van-checkbox icon-size="17px" shape="square" name="{{item.id}}"></van-checkbox>
		</view>
		<view style="flex:1;background:white;">
			<van-card custom-class="goods-card" price="{{item.price*item.num/100}}元" desc="{{item.sku_desc}}" title="{{item.goods_name}}" thumb="{{item.goods_image}}">
				<view slot="footer">
					<van-stepper data-num="{{item.num}}" data-id="{{item.id}}" bind:change="onCartGoodsNumChanged" value="{{item.num}}" step="1" />
				</view>
			</van-card>
		</view>
	</view>
</van-checkbox-group>
</block>

<van-submit-bar bind:submit="onCartConfirm" wx:if="{{!editMode}}" price="{{ totalPrice }}" button-text="提交订单">
	<van-checkbox value="{{ allIsSelected }}" bind:change="onSelectAll" shape="square">全选</van-checkbox>
	<view wx:if="{{false}}" slot="tip">您的收货地址</view>
</van-submit-bar>

<van-cell-group wx:else title="" style="position: fixed;bottom: 0;left: 0;width: 100%;">
	<van-cell>
		<view slot="title">
			<van-checkbox value="{{ allIsSelected }}" bind:change="onSelectAll" shape="square" name="all">
				全选
			</van-checkbox>
		</view>
		<van-button bindtap="removeCartGoods" size="mini" slot="right-icon" plain type="info">删除</van-button>
	</van-cell>
</van-cell-group>

<LoginPanel show="{{showLoginPanel}}"></LoginPanel>
/* miniprogram/pages/cart/index.wxss */
.goods-card{
  background-color: #fefefe !important;
}
.goods-card-container {
  display:flex;margin:10px;background:#fefefe;
}

.goods-card-container + .goods-card-container{
  padding-top: 10px;
}

二、效果

在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。