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