全选、反选、单选、数量加减、价格和总数量计算都有;后期有时间再加入左滑删除的功能
可以单独做成一个组件,只需要动态传入一个购物车的数组即可,这里就只说直接用的了
shopcart.wxml
1、主要利用了checkbox-group
和checkbox
组件来实现
2、全选的时候通过一个checkbox来包裹住并设置value="all"
,然后改变每一个checkbox的checked属性,这样简单点
<!--pages/shopcart/shopcart.wxml-->
<view class="shopcart-main-container">
<view class="opertion-container">
<view class="address">山东省青岛市xxxxxxxxxxxxxxxxx</view>
<view class="edit" bindtap="onClickEdit">编辑商品</view>
</view>
<checkbox-group bindchange="handleShopChange">
<view style="{{item.txtStyle}}" class="shop-item {{item.isTouchMove?'touch-move-active':''}}" wx:for="{{goodsList}}" wx:key="index" data-id="{{item.goods_id}}">
<label class="shopcart-label" style="display:flex;align-items:center;{{item.txtStyle}}" data-id="{{item.goods_id}}" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd">
<checkbox value="{{item.goods_id}}" checked="{{item.checked}}" />
<view style="display:flex">
<image></image>
<view class="content">
<view class="good-info">
<text class="name">{{item.goods_name}}</text>
<text style="color:#ccc;font-size:25rpx;margin-top:10rpx">我是商品的规格</text>
</view>
<view class="good-price-num">
<text>¥{{item.goods_price}}</text>
<view class="amount">
<view style="color:{{item.sales_num===1?'#c0c0c0':'#000'}};font-size:32rpx" data-type="decrease" data-id="{{item.goods_id}}" catchtap="handleCountChange">-</view>
<view style="width:60rpx;margin:0 15rpx">{{item.sales_num}}</view>
<view style="color:{{item.sales_num>=10?'#c0c0c0':'#000'}}" data-type="add" data-id="{{item.goods_id}}" catchtap="handleCountChange">+</view>
</view>
</view>
</view>
</view>
</label>
</view>
</checkbox-group>
<!-- 底部 -->
<view class="bottom-container">
<view class="bottom-wrapper">
<view class="inner">
<checkbox-group bindchange="onSelectAll">
<label class="checkall">
<checkbox value="all" checked="{{isAllChecked}}"></checkbox>
<text>全选</text>
</label>
</checkbox-group>
</view>
</view>
<view class="settlement" bindtap="onPayOrDelete">
<text class="total-text" wx:if="{{status==='pay'}}">¥{{totalPrice}}</text>
<view class="pay">{{status==='pay'?'去结算':'删除'}}({{totalCount}})</view>
</view>
</view>
</view>
shopcart.wxss
/* pages/shopcart/shopcart.wxss */
.shopcart-main-container {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
.opertion-container {
display: flex;
align-items: center;
justify-content: space-between;
width: 700rpx;
}
.address {
width: 350rpx;
color: #FF9400;
font-size: 28rpx;
overflow: hidden;
font-weight: bold;
white-space: nowrap;
text-overflow: ellipsis;
}
.edit {
color: #ef5656;
font-size: 28rpx;
font-weight: bold;
}
.shop-item {
width: 700rpx;
overflow: hidden;
margin-top: 35rpx;
padding-bottom: 30rpx;
border-bottom: 1px solid #f1f1f1;
}
.touch-wrapper {
width: 100%;
margin-right: 0;
-webkit-transition: all 0.4s;
transition: all 0.4s;
-webkit-transform: translateX(90rpx);
transform: translateX(90rpx);
margin-left: -90rpx;
}
.shop-item:last-child {
border-bottom: 0;
margin-bottom: 100rpx;
}
image {
width: 160rpx;
height: 160rpx;
margin: 0 25rpx;
border-radius: 15rpx;
background-color: red;
}
.good-info {
display: flex;
flex-direction: column;
color: #3D444D;
}
.good-price-num {
display: flex;
align-items: center;
justify-content: space-between;
width: 430rpx;
margin-top: 30rpx;
}
.amount {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
}
.amount view {
width: 50rpx;
line-height: 40rpx;
text-align: center;
background-color: #f1f1f1;
}
/* 修改checkbox样式 */
checkbox .wx-checkbox-input {
border-radius: 50%;
transform: scale(0.8);
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border-color: #FF9A00;
background-color: #FF9A00;
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
color: #fff;
font-size: 25rpx;
line-height: 20rpx;
text-align: center;
transform: scale(0.8);
background: transparent;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
/* 底部 */
.bottom-container {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 90rpx;
background-color: #fff;
box-shadow: 12rpx 0 15rpx rgba(0, 0, 0, 0.16)
}
.bottom-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
}
.checkall {
display: flex;
align-items: center;
color: #333;
font-size: 26rpx;
margin-left: 25rpx;
}
.settlement {
display: flex;
align-items: center;
justify-content: center;
height: 60rpx;
color: #fff;
margin-right: 30rpx;
}
.total-text {
color: #ef5656;
font-size: 33rpx;
font-weight: bold;
margin-right: 15rpx;
}
.total-text::before {
content: '合计:';
color: #3D444D;
font-weight: 400;
}
.pay {
font-size: 26rpx;
padding: 10rpx 20rpx;
border-radius: 50rpx;
background-color: red;
}
shopcart.js
// pages/shopcart/shopcart.js
Page({
/**
* 页面的初始数据
*/
data: {
goodsList: [
{
goods_name: '上衣',
goods_price: 10,
sales_num: 1,
goods_stock: 10,
goods_id: '0'
},
{
goods_name: '裤子',
goods_price: 20,
sales_num: 1,
goods_stock: 8,
goods_id: '1'
},
{
goods_name: '鞋子',
goods_price: 30,
sales_num: 1,
goods_stock: 8,
goods_id: '2'
},
{
goods_name: '袜子',
goods_price: 40,
sales_num: 1,
goods_stock: 15,
goods_id: '3'
},
{
goods_name: '帽子',
goods_price: 25,
sales_num: 1,
goods_stock: 15,
goods_id: '4'
},
{
goods_name: '眼镜',
goods_price: 30,
sales_num: 1,
goods_stock: 20,
goods_id: '5'
}
],
isAllChecked: false, //是否全选
checkedArr: [], //复选框选中的值
totalPrice: 0,
totalCount: 0,
status: 'pay',//pay结算,delete删除编辑状态
},
//选择购物车商品
handleShopChange(e){
let { goodsList, isAllChecked } = this.data
let values = e.detail.value
for (let item of goodsList) {
//有时候id可能是number也有可能是string,这里做统一string处理
let goodId = String(item.goods_id)
// 如果要检索的字符串值没有出现,则返回 -1。
values.indexOf(goodId) >= 0 ? item.checked = true : item.checked = false
}
let length = values.length
// 如果选择的数组中有值,并且长度等于列表长度,就是全选
length > 0 && length === goodsList.length ? isAllChecked = true : isAllChecked = false
this.setData({
isAllChecked
})
this.calTotalCountPrice()
},
//加减数量
handleCountChange(e){
const { type, id } = e.currentTarget.dataset
let { goodsList } = this.data
if (type === 'add') {
//最大数量显示10个
if (goodsList[id].sales_num >= 10) return
goodsList[id].sales_num++
} else {
//最小数量限制一个
if (goodsList[id].sales_num === 1) return
goodsList[id].sales_num--
}
this.setData({
goodsList
})
this.calTotalCountPrice()
},
//全选
onSelectAll(e){
let { goodsList, isAllChecked } = this.data
let values = e.detail.value
for (let i = 0; i < goodsList.length; i++) {
goodsList[i].checked = false
if (values[0] === 'all') {
isAllChecked = true
goodsList[i].checked = true
} else {
isAllChecked = false
goodsList[i].checked = false
}
}
this.setData({
isAllChecked,
goodsList
})
this.calTotalCountPrice()
},
//购物车状态
onClickEdit(){
let { status } = this.data
if (status === 'pay'){
this.setData({
status: 'delete'
})
return
}
this.setData({
status: 'pay'
})
},
//计算总数和价格
calTotalCountPrice(){
let { goodsList, totalCount, totalPrice } = this.data
//每次执行的时候初始化,防止重复计算
totalCount = 0
totalPrice = 0
for (let i = 0; i < goodsList.length; i++) {
//如果都是选中的状态在计算
if (goodsList[i].checked) {
totalCount += 1
totalPrice += goodsList[i].goods_price * goodsList[i].sales_num
}
}
this.setData({
totalCount,
totalPrice: totalPrice.toFixed(2)
})
},
//结算和删除
onPayOrDelete(){
const { status } = this.data
console.log(status)
status === 'delete' && this.deleteShopCartList()
status === 'pay' && this.payShopCartPrice()
},
deleteShopCartList(){
wx.showToast({
title: 'delete',
})
},
payShopCartPrice(){
wx.showToast({
title: 'pay price',
})
},
onShow: function () {
},
onPullDownRefresh: function () {
},
onReachBottom: function () {
},
})