在我的GitHub上有校园二手交易微信小程序的源码,这里面包含了购物车的功能,GitHub地址:https://github.com/zhuyuzhu/Secondhand-goods-on-campus,该项目的pages文件夹下的shoppingCart文件夹就是购物车的代码。
购物车功能实现的逻辑:
(1)从服务器拿到的物品数据data里面,只有物品的信息,我们需要给每个物品数据中加入一个是否选中的属性
这样当我们在点击选择按钮的时候,就可以选中该物品,当再次点击的时候,就可以取消选择。
其中几个主要的功能:
(1)物品请求数据,使用微信小程序request请求,POST方式得到服务器传来的物品数据。
每次请求要想后端传入用户id和物品id(物品id根据后端要求进行处理,我每次传入请求到的物品中最后一个物品的id,后端会把这个id之后的5个值再传给前端)才得到的物品数据,每一次请求要判断还有没有数据,有数据则请求成功,没有数据就不请求。
(2)选中和取消选中单个物品
(3)选中或取消选中物品时,总价格要进行加减
每次触发选择事件,都会触发计算总价的方法
(4)全选按钮,实现物品的全选
当用户通过单选选择了所有物品时,“全选按钮”会自动改变为选中样式;当用户通过“全选按钮”选择所有商品的时候,每个商品都应该是选中状态。
(5)计算总价
任何一次触发该函数,都会重新计算价格,将总价变为0,再进行选中项的价格累加,而不是在原总价上累加或减某一个商品的价格
wxml代码:
<!--pages/shoppingCart/shoppingCart.wxml--><view class='box'> <view class='wrapper'> <view class="tab-content {{selectBook? 'select': 'noSelect'}}" bindtap='chooseBookCart'>书本</view> <view class="tab-content {{selectThing? 'select': 'noSelect'}}" bindtap='chooseThingCart'>物品</view> </view></view><!-- 书本 --><view class="cart-box" wx:if="{{selectBook}}"> <!-- wx:for 渲染购物车列表 --> <view wx:for="{{carts}}" wx:key="{{carts}}" class='cart-goods'> <!-- wx:if 是否选择显示不同图标 --> <view class='icon-wrapper' bindtap="selectList" data-index="{{index}}"> <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red" /> <icon wx:else type="circle" class='cart-icon' /> </view> <view class='cart-img'> <image class="cart-thumb" src="{{item.picture}}"></image> <view class='cart-message'> <text class='name'>书名:{{item.bname}}</text> <text class='author'>作者:{{item.author}}</text> <text class='press'>出版社:{{item.press}}</text> <text class='price'>价格:¥{{item.bprice}}</text> </view> </view> <!-- 点击商品图片可跳转到商品详情 --> <!-- 删除按钮 --> <text bindtap="deleteList" data-index="{{index}}" class='delete'> × </text> </view> <view wx:if="{{isMyCartShow}}" class='bottom'>没有书本啦~_~</view></view><!-- 物品 --><view class="cart-box" wx:if="{{selectThing}}"> <!-- wx:for 渲染购物车列表 --> <view wx:for="{{thingCarts}}" wx:key="{{thingCarts}}" class='cart-goods'> <!-- wx:if 是否选择显示不同图标 --> <view class='icon-wrapper' bindtap="selectListThing" data-index="{{index}}"> <icon wx:if="{{item.selected}}" class='cart-icon' type="success" color="red" /> <icon wx:else type="circle" class='cart-icon' /> </view> <view class='cart-img'> <image class="cart-thumb" src="{{item.gpicture}}"></image> <view class='cart-message'> <text class="name">{{item.gname}}</text> <text class="author">校区:{{item.gcollege}}</text> <text class='author'>成色:{{item.gstatus}}</text> <text class='author'>发布者:{{item.usersname}}</text> <text class='price'>¥{{item.gprice}}</text> </view> </view> <!-- 点击商品图片可跳转到商品详情 --> <!-- 删除按钮 --> <text bindtap="deleteListThing" data-index="{{index}}" class='delete'> × </text> </view> <view wx:if="{{isThingCartShow}}" class='bottom'>没有物品啦~_~</view></view><!-- 底部操作栏 --><view class='cart-bottom'> <!-- wx:if 是否全选显示不同图标 --> <icon wx:if="{{selectAllStatus}}" class='cart-iconAll' type="success_circle" color="red" bindtap="selectAll" /> <icon wx:else type="circle" class='cart-iconAll' color="#ff7100" bindtap="selectAll" /> <text class='cart-allSelect' bindtap="selectAll">全选</text> <!-- 总价 --> <text class='cart-allPrice'>合计:</text> <text class='allPrice'>¥{{totalPrice}}</text> <button class='btn-red' bindtap='toBuy' form-type='submit'>去结算</button></view>wxss代码:
/* pages/shoppingCart/shoppingCart.wxss */.wrapper { position: fixed; top: 0rpx; display: flex; width: 100%; height: 50rpx; justify-content: space-around; background-color: #fff; z-index: 9999;}.select { text-align: center; width: 50%; background-color: green; color: #fff;}.noSelect { width: 50%; text-align: center;}.cart-box { margin-top: 50rpx; margin-bottom: 100rpx;}.cart-goods { display: flex; flex-direction: row; padding: 30rpx; border-bottom: 3rpx solid #e6e6e6;}.icon-wrapper { line-height: 260rpx;} .cart-icon { display: inline-block; margin: auto 10rpx; margin-left: -10rpx; } .cart-img { display: flex; width: 580rpx; height: 260rpx;}.cart-img image{ margin: auto 0rpx; width: 165rpx; height: 225rpx;} .cart-goods .cart-message { width: 380rpx; display: flex; flex-direction: column; margin: 0 20rpx; justify-content: space-around; } .name{ font-weight: 600; color: #4a4a4a; font-size: 32rpx; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;} .author, .press{ font-size: 28rpx; color: #9e9e9e; font-weight: 300; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .price { font-size: 28rpx; color: #f40; font-weight: 300; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .delete { position: absolute; right: 40rpx; margin-top: -10rpx; } .cart-bottom { position: fixed; width: 100%; height: 100rpx; background-color: white; bottom: 0rpx; } .cart-allPrice { float:left; padding: 0.5rem; font-weight: 100; margin-left: 70rpx; } .allPrice { float:left; padding: 0.5rem; font-weight: 100; margin-left: -30rpx; color: #f40; } .cart-allSelect { float:left; padding: 0.5rem; margin-left: -23rpx; font-weight: 100 } .cart-iconAll { float:left; padding: 0.5rem; margin-top: 7rpx; } .btn-red { background-color: #f44336; /* 红色 */ font-size: 40rpx;}button { position: fixed; right: 0; color: white; text-align: center; display: inline-block; font-size: 30rpx; border-radius: 0rpx; width: 30%; height: 100rpx; line-height: 100rpx;}.cart-list { display: flex; flex-direction: column;}.bottom { color: #666; text-align: center; font-size: 30rpx;}微信js代码:
// pages/shoppingCart/shoppingCart.jsvar app = getApp();const orginalPrice = 0; //由于0.00在赋值时是0,用toFixed()取余Page({ /** * 页面的初始数据 */ data: { selectTab: true, selectBook: true, selectThing: false, carts: [], // 购物车列表 hasList: false, // 列表是否有数据 totalPrice: orginalPrice.toFixed(2), // 总价,初始为0 selectAllStatus: false, // 全选状态,默认全选 bookId: '', isMyCartShow: false, studentId: '', myCartBookLength: '5', bookPrice: 0, thingId: '', thingCarts: [], // 物品列表 isThingCartShow: false, myCartThingLength: '5', thingPrice: 0, }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { var that = this; var studentId = that.data.studentId; var hasList = that.data.hasList; try { var value = wx.getStorageSync('studentIdSync') if (value) { console.log(value); //同步得到studentId的值 that.setData({ studentId: value }) } } catch (e) { console.log(0); } this.getBookCartList() }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { // 动态设置导航条标题 wx.setNavigationBarTitle({ title: '购物车' }); wx.showNavigationBarLoading(); //在标题栏中显示加载图标 setTimeout(function(){ wx.stopPullDownRefresh(); //停止加载 wx.hideNavigationBarLoading(); //隐藏加载icon },2000) }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { if (this.data.selectBook){ this.getBookCartList() }else { this.getThingCartList() } },getBookCartList(){ console.log(1); var that = this; var url = app.globalData.huanbaoBase + 'getbooksbystudentid.php' var ismyCartShow = that.data.ismyCartShow; var carts = that.data.carts; var bookId = that.data.bookId; var myCartBookLength = that.data.myCartBookLength; var studentId = that.data.studentId; console.log(bookId, myCartBookLength); // if (myCartBookLength < 5) { // that.setData({ // isMyCartShow: true // }) // return // } wx.showToast({ title: '加载中', icon: 'loading', duration: 1000, }) wx.request({ url, method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded ' }, data: { //此处设置,一定要与后台一一对应,属性名和属性的先后位置。 studentId: studentId, lastId: bookId, }, success: res => { var carts = that.data.carts || []; var data = res.data.data; console.log(data); if(data === undefined) { wx.hideToast() that.setData({ isMyCartShow: true }) return } that.setData({ myCartBookLength: data.length //每次获取5组值 }) myCartBookLength = data.length; that.setData({ bookId: res.data.data[myCartBookLength - 1].bookid }) console.log(myCartBookLength); data.forEach(item => { let messege = { selected: false, ...item } carts.push(messege); //实现购物车的最近添加的物品,展现在最前面 }) that.setData({ carts: carts , }) }, fail: err => { console.log(err); } })}, getThingCartList() { console.log(1); var that = this; var url = app.globalData.huanbaoBase + 'getthingsbystudentid.php' var isThingCartShow = that.data.isThingCartShow; var thingCarts = that.data.thingCarts; var thingId = that.data.thingId; var myCartThingLength = that.data.myCartThingLength; var studentId = that.data.studentId; var selectBook = that.data.selectBook; var selectThing = that.data.selectThing; console.log(thingId, myCartThingLength); // if (myCartThingLength < 5) { // that.setData({ // isThingCartShow: true // }) // return // } wx.showToast({ title: '加载中', icon: 'loading', duration: 1000, }) wx.request({ url, method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded ' }, data: { //此处设置,一定要与后台一一对应,属性名和属性的先后位置。 studentId: studentId, lastId: thingId, }, success: res => { var thingCarts = that.data.thingCarts || []; var data = res.data.data; console.log(data); if (data === undefined) { wx.hideToast() that.setData({ isThingCartShow: true }) return } that.setData({ myCartThingLength: data.length //每次获取5组值 }) myCartThingLength = data.length; that.setData({ thingId: res.data.data[myCartThingLength - 1].goodid }) console.log(myCartThingLength); data.forEach(item => { let messege = { selected: false, ...item } thingCarts.push(messege); //实现购物车的最近添加的物品,展现在最前面 }) that.setData({ thingCarts: thingCarts, }) }, fail: err => { console.log(err); } }) }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, //计量总价 getTotalPrice() { let carts = this.data.carts; // 获取购物车列表 let thingPrice = parseFloat(this.data.thingPrice); let bookPrice = parseFloat(this.data.bookPrice); let total = 0.00; for (let i = 0; i < carts.length; i++) { // 循环列表得到每个数据 if (carts[i].selected) { // 判断选中才会计算价格 total += parseFloat(carts[i].bprice); // 所有价格加起来 } } this.setData({ bookPrice: total.toFixed(2) }) total += thingPrice; this.setData({ // 最后赋值到data中渲染到页面 carts: carts, totalPrice: total.toFixed(2) //保留小数后面2两位 }); }, //选择事件 selectList(e) { let that = this; const index = e.currentTarget.dataset.index; // 获取data- 传进来的index console.log(index); let selectAllStatus = that.data.selectAllStatus; //是否已经全选 let str = true; //用str与每一项进行状态判断 let carts = that.data.carts; // 获取购物车列表 const selected = carts[index].selected; // 获取当前商品的选中状态 carts[index].selected = !selected; // 改变状态 that.setData({ carts: carts }); that.getTotalPrice(); // 重新获取总价 for (var i = 0; i < carts.length; i++) { str = str && carts[i].selected; //用str与每一项进行状态判断 } if (str === true) { that.setData({ selectAllStatus: true }) } else { that.setData({ selectAllStatus: false }) } }, //全选事件 selectAll(e) { var that = this; let selectAllStatus = that.data.selectAllStatus; // 是否全选状态 let carts = that.data.carts; let thingCarts = that.data.thingCarts; var selectThing = that.data.selectThing; var selectBook = that.data.selectBook; if(selectBook) { selectAllStatus = !selectAllStatus; for (let i = 0; i < carts.length; i++) { carts[i].selected = selectAllStatus; // 改变所有商品状态 } that.setData({ selectAllStatus: selectAllStatus, carts: carts }); that.getTotalPrice(); // 重新获取总价 if (carts.length === 0) { //当没有物品时,不能再点“全选” wx.showModal({ title: '提示', content: '购物车空空如也~', success: function (res) { //模糊层成功出来后 if (res.confirm) { console.log('用户点击确定') that.setData({ selectAllStatus: false }) } else { console.log('用户点击取消') that.setData({ selectAllStatus: false }) } }, }) } }else { selectAllStatus = !selectAllStatus; for (let i = 0; i < thingCarts.length; i++) { thingCarts[i].selected = selectAllStatus; // 改变所有商品状态 } that.setData({ selectAllStatus: selectAllStatus, thingCarts: thingCarts }); that.getTotalPriceThing(); // 重新获取总价 if (thingCarts.length === 0) { //当没有物品时,不能再点“全选” wx.showModal({ title: '提示', content: '购物车空空如也~', success: function (res) { //模糊层成功出来后 if (res.confirm) { console.log('用户点击确定') that.setData({ selectAllStatus: false }) } else { console.log('用户点击取消') that.setData({ selectAllStatus: false }) } }, }) } } }, //删除商品 deleteList(e) { const index = e.currentTarget.dataset.index; var selectAllStatus = this.data.selectAllStatus; let carts = this.data.carts; let totalPrice = this.data.totalPrice; wx.showModal({ title: '提示', content: '将此产品移除购物车?', success: res=> { if (res.confirm) { console.log('用户点击确定') carts.splice(index, 1); // 删除购物车列表里这个商品 this.setData({ carts: carts }); if (carts.length == 0) { // 如果购物车为空 this.setData({ hasList: false, // 修改标识为false,显示购物车为空页面 selectAllStatus: false, totalPrice: orginalPrice.toFixed(2) //此时价格为0 }); } else { // 如果不为空 this.getTotalPrice(); // 重新计算总价格 } } else if (res.cancel) { console.log('用户点击取消') } } }) },// 物品 //计量总价 getTotalPriceThing() { let thingCarts = this.data.thingCarts; // 获取购物车列表 let total = 0; //注意后台返回的是字符串数字。 let thingPrice = parseFloat(this.data.thingPrice); let bookPrice = parseFloat(this.data.bookPrice); for (let i = 0; i < thingCarts.length; i++) { // 循环列表得到每个数据 if (thingCarts[i].selected) { // 判断选中才会计算价格 total += parseFloat(thingCarts[i].gprice); // 所有价格加起来 } } this.setData({ thingPrice: total }) total += bookPrice; this.setData({ // 最后赋值到data中渲染到页面 thingCarts: thingCarts, totalPrice: total.toFixed(2) //保留小数后面2两位 }); }, //选择事件 selectListThing(e) { let that = this; const index = e.currentTarget.dataset.index; // 获取data- 传进来的index console.log(index); let selectAllStatus = that.data.selectAllStatus; //是否已经全选 let str = true; //用str与每一项进行状态判断 let thingCarts = that.data.thingCarts; // 获取购物车列表 const selected = thingCarts[index].selected; // 获取当前商品的选中状态 thingCarts[index].selected = !selected; // 改变状态 that.setData({ thingCarts: thingCarts }); that.getTotalPriceThing(); // 重新获取总价 for (var i = 0; i < thingCarts.length; i++) { str = str && thingCarts[i].selected; //用str与每一项进行状态判断 } console.log(str); if (str === true) { that.setData({ selectAllStatus: true }) } else { that.setData({ selectAllStatus: false }) } }, //删除商品 deleteListThing(e) { const index = e.currentTarget.dataset.index; var selectAllStatus = this.data.selectAllStatus let thingCarts = this.data.thingCarts; let totalPrice = this.data.totalPrice; wx.showModal({ title: '提示', content: '将此产品移除购物车?', success: res=> { if(res.confirm){ console.log("用户点了确定") thingCarts.splice(index, 1); // 删除购物车列表里这个商品 this.setData({ thingCarts: thingCarts }); if (thingCarts.length == 0) { // 如果购物车为空 this.setData({ hasList: false, // 修改标识为false,显示购物车为空页面 selectAllStatus: false, totalPrice: orginalPrice.toFixed(2) //此时价格为0 }); } else { // 如果不为空 this.getTotalPrice(); // 重新计算总价格 } }else if(res.cancel) { console.log("用户点了取消") } } }) }, chooseBookCart() { var that = this; var selectBook = that.data.selectBook; var selectThing = that.data.selectThing; let selectAllStatus = that.data.selectAllStatus; //是否已经全选 let str = true; //用str与每一项进行状态判断 let carts = that.data.carts; for (var i = 0; i < carts.length; i++) { str = str && carts[i].selected; //用str与每一项进行状态判断 } console.log(str); that.setData({ selectBook: true, selectThing: false, }) }, chooseThingCart() { var that = this; var selectThing = that.data.selectThing; var selectBook = that.data.selectBook; var selectAllStatus = that.data.selectAllStatus; that.setData({ selectBook: false, selectThing: true, }) // 此时data中的数据改变,但是此时的属性值还未改变 that.getThingCartList() }, toBuy(){ var totalPrice = this.data.totalPrice; var thingCarts = this.data.thingCarts; var bookCarts = this.data.carts; var bookId = this.data.bookId; var bookCart = [], thingCart = []; bookCarts.forEach(item=>{ if (item.selected){ bookCart.push(item); } }) thingCarts.forEach(item=>{ if (item.selected){ thingCart.push(item); } }) let shoppingCartList = {thingCart, bookCart}; console.log(bookCart); if(totalPrice === '0.00'){ console.log(totalPrice); }else { console.log(shoppingCartList); wx.navigateTo({ url: '../settlement/settlement?bookCart='+bookCart, }) } }})后端代码和数据库有时间再写吧。。。
微信小程序













