购物车功能基本上算是每个商城都有的功能,也是整个商城系统最重要的部分,购物车的做法有很多种,一般存放在本地缓存和数据库中比较常见,本文就是存放到了数据库中;
先放一张效果图:
先分析下要实现的功能:
1.数量的加减
2.单选、多选、全选
3.根据选中商品单价和数量计算金额
wxml:
<block wx:if='{{hasList}}'> <!-- <>购物车列表 --> <view class="carts-list"> <view wx:for="{{carts}}" class="carts-item" wx:key='cart' wx:item='item'> <!-- //复选框 --> <view class="carts-radio"> <image class="carts-select" bindtap="bindCheckbox" data-index="{{index}}" src="{{item.isSelect?'/img/icon/select.png':'/img/icon/n_select.png'}}" /> </view> <!-- //商品信息 --> <view class="carts-cnt"> <image class="carts-image" src="{{imghref}}{{item.goods_img}}" mode="aspectFill" /> <view class="carts-info"> <view class="carts-title clamp2">{{item.goods_name}}</view> <text class="carts-guige">{{item.guige}}ml</text> <view class="carts-subtitle"> <text class="carts-price c--f60">¥{{item.price}}</text> </view> </view> </view> <!-- //数量加减 --> <view class="carts-num"> <text class="minus" bindtap="bindMinus" data-index='{{index}}'>-</text> <input type="number" bindinput="bindIptCartNum" data-index='{{index}}' value="{{item.num}}" /> <text class="plus normal" data-index='{{index}}' bindtap="bindPlus">+</text> </view> <!-- //删除 --> <icon class="carts-del" type="clear" size="16" color="#ccc" data-index="{{index}}" bindtap="bindCartsDel" /> </view> </view> <view class="carts-footer"> <view class="bottomfixed"> <view class="inner"> <view class="chkAll" bindtap="bindSelectAll"> <image class="allselect" src="{{selectAllStatus?'/img/icon/select.png':'/img/icon/n_select.png'}}" /> <text>全选</text> </view> <view class="total">合计:<em>¥{{totalMoney}}</em></view> <view wx:if="{{totalCount != 0}}" class="btn-pay" bindtap='bindjiesuan'>去结算({{totalCount}})</view> <view wx:else class="btn-pay disabled">去结算({{totalCount}})</view> </view> </view> </view> </block> <block wx:else> <view class="content" > <view style="margin-top:50px;width:100%;"> <view style='font-size:15px;'>购物车没有商品!</view> </view> </view> </block>
hasList 用于判断购物车中是否有数据
<!-- //复选框 --> <view class="carts-radio"> <image class="carts-select" bindtap="bindCheckbox" data-index="{{index}}" src="{{item.isSelect?'/img/icon/select.png':'/img/icon/n_select.png'}}" /> </view>
这里的选择框我用了两个图片代替,一个是选中状态的图片,一个是非选中状态的图片,需要的话可以自行到iconfont去下载
wxss:
.c--f60{color: #f60;}.clamp1, .clamp2, .clamp3{display: -webkit-box!important; overflow: hidden; -webkit-box-orient: vertical;}.clamp1{-webkit-line-clamp:1;}.clamp2{-webkit-line-clamp:2;}.clamp3{-webkit-line-clamp:3;} .carts-list{ padding: 0 20rpx;} .carts-list .carts-item{ border-top: 1rpx solid #e3e3e3; box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; padding: 20rpx 10rpx; width: 100%; position: relative;}.carts-list .carts-item:nth-child(1){ border-top: 0;} .carts-select{ margin-top:5px; width:30px; height:30px;} .carts-item .carts-cnt{ flex: 1; padding: 0 20rpx;}.carts-cnt .carts-image{ float:left; margin-right: 20rpx; height: 150rpx; width: 150rpx; }.carts-cnt .carts-info{ display: flex; flex-direction: column; justify-content: space-between; min-height: 150rpx;}.carts-cnt .carts-title{ font-size:15px;}.carts-cnt .carts-guige{ font-size: 12px;}.carts-cnt .carts-subtitle{ display: flex; flex-direction: row; font-size: 15px;}.carts-list .carts-item .carts-del{ position: absolute; top: 20rpx; right: 10rpx;} /*数量加减*/ .carts-num{ border: 1rpx solid #aaa; border-radius: 5rpx; display: flex; align-items: center; align-self: flex-end; text-align: center; height: 50rpx;} .carts-num input{ border-left: 1rpx solid #aaa; border-right: 1rpx solid #aaa; font-size: 30rpx; font-family: arial; height: 50rpx; line-height: 50rpx; width: 80rpx;}.carts-num .minus, .carts-num .plus{color: #000; text-align: center; line-height: 50rpx; width: 40rpx;}.carts-num .minus{font-size: 30rpx;}.carts-num .minus.disabled{color: #ccc;}.carts-num .plus{font-size: 34rpx;} .bottomfixed{ position: fixed; display: flex; flex-direction: column; bottom: 0; width: 100%; height: 120rpx; line-height: 120rpx; background: #f5f5f5;} .bottomfixed .inner{ display: flex; flex-direction: row; align-items: center;} .bottomfixed .inner .chkAll { font-size: 28rpx; margin-right: 40rpx; margin-left: 20rpx; display: flex; flex-direction: row; align-items: center;} .bottomfixed .inner .chkAll .allselect{ width:30px; height:30px;} .bottomfixed .inner .total{ font-size:28rpx;}.bottomfixed .inner .total em{color:#f60;} .btn-pay{ position: absolute; right:0px; background:#FF5E3A; color:#fff; padding:0 10px; font-size: 28rpx;} .disabled{ background:#ccc;} .content{ width: 100%; height:100%; position: absolute; left: 0; font-size: 15px; color:#999; text-align:center;}
js:
Page({ /** * 页面的初始数据 */ data: { hasList: true,//购物车是否有数据 totalMoney: 0,//总金额 selectAllStatus: false,//是否全选 uid: 0, //用户ID totalCount: 0,//数量 carts: [], }, //设置文本框值 bindIptCartNum: function (e) { const index = e.currentTarget.dataset.index; var num = e.detail.value; let carts = this.data.carts; carts[index].num = num; this.setData({ carts: carts }); }, /* 点击减号 */ bindMinus: function (e) { const index = e.currentTarget.dataset.index; let carts = this.data.carts; let num = carts[index].num; if (num <= 1) { return false; } num = num - 1; carts[index].num = num; this.setData({ carts: carts }); this.getTotalPrice(); }, /* 点击加号 */ bindPlus: function (e) { const index = e.currentTarget.dataset.index; let carts = this.data.carts; let num = carts[index].num; num = num + 1; carts[index].num = num; this.setData({ carts: carts }); this.getTotalPrice(); }, //删除商品 bindCartsDel(e) { var that = this; wx.showModal({ title: '提示', content: '您确定要删除吗?', success: function (res) { if (res.confirm) { //网络请求删除购物车数据 } } }) }, //计算总价 getTotalPrice() { let carts = this.data.carts; // 获取购物车列表 let total = 0; let num = 0; for (let i = 0; i < carts.length; i++) { // 循环列表得到每个数据 if (carts[i].isSelect) { // 判断选中才会计算价格 total += carts[i].num * carts[i].price; // 所有价格加起来 num += carts[i].num; } } this.setData({ // 最后赋值到data中渲染到页面 carts: carts, totalCount: num, totalMoney: total.toFixed(2) }); }, //绑定单选 bindCheckbox: function (e) { var that = this; const idx = e.currentTarget.dataset.index; let carts = that.data.carts; const isSelect1 = carts[idx].isSelect; carts[idx].isSelect = !isSelect1; that.setData({ carts: carts, selectAllStatus: false }); that.getTotalPrice(); }, //绑定多选 bindSelectAll: function (e) { var that = this; let selectedAllStatus = that.data.selectAllStatus; let carts = that.data.carts; selectedAllStatus = !selectedAllStatus; for (var i = 0; i < carts.length; i++) { carts[i].isSelect = selectedAllStatus; } that.setData({ carts: carts, selectAllStatus: selectedAllStatus }); that.getTotalPrice(); }, //购物车结算 bindjiesuan: function () { var that = this; let carts = that.data.carts; let jscart = []; var j = 0 for (var i = 0; i < carts.length; i++) { if (carts[i].isSelect) { jscart[j] = carts[i]; j++; } } if (jscart.length <= 0) { wx.showToast({ title: '未选择商品', icon: 'success', duration: 1000 }) return; } wx.setStorageSync('jscart', jscart);//存入缓存 //转到结算页面 wx.navigateTo({ url: 'jiesuan?amount=' + that.data.totalMoney }); }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, //加载购物车 getCart: function () { var that = this; var uid = that.data.uid; //网络请求获取购物车数据 }})