小程序关于购物车功能的实现总结
一、 要求:
1、 能添加购物车,要求不重复,若添加相同的商品,则数量上加1,
2、 给购物车添加复选框按钮,点击或取消复选框时,可自动计算总价,
3、 当在复选框选中的情况下,可点击增加或减少某商品的数量,并实时计算商品总价,
4、 可管理购物车,如删除操作。
效果图:
二、 解决思路
2.1、解决添加购物车,并不重复,当添加相同的商品时,商品数量加1.
建立储存购物车信息数组:shopCarStore,可储存本地,储存的本地的目的是,当在商品页面添加好商品后,可在“我的购物车”页面通过wx.getStore获得。因为本地储存只能全覆盖不能追加,故在储存通过追加再储存,
添加购物车代码:
// detail.wxml
<button class='joinshop' bindtap='joinshop' style="position: fixed; bottom:0;">加入购物车</button>
<button class='immedbuy' bindtap='immedbuy' style="position: fixed; bottom:0;">立即购买</button>
// detail.js
joinshop:function(){
var that = this;
if (this.data.shopCarStore.length!=0){
var isFind = false;
for(var i=0;i<this.data.shopCarStore.length;i++){
if (app.appGoodInfo.goodInfo.pro_id == this.data.shopCarStore[i].pro_id){
this.data.shopCarStore[i].goodNumber = this.data.shopCarStore[i].goodNumber+1;
isFind = true;
}else{
isFind = false;
//点击加入购物车后,将app.appGoodInfo.goodInfo追加数组shopCarStore中
}
}
if (isFind == false ) {
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
}else{
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
// 再将shopCarStore存储到本地
wx.setStorage({
key: 'shopCarStore',
data: that.data.shopCarStore,
success:function(e){
wx.showToast({
title: '已加入购物车',
icon: 'success',
duration: 1000
})
},
fail: function () {
wx.showToast({
title: '添加失败',
icon: 'none',
duration: 1000
})
}
})
},
**实现思路:**添加购物车的实质是将光标所点击的商品的信息储存的本地shopCarStore[](可自命名),在购物车页面获得本地信息并显示,当添加相同第二件商品时,通过for循环那遍历数组寻找商品的唯一标记值pro_id,若找到,则将该行数储存数据中商品数量值+1,(有些很多细节需要注意,比如知道加入购物车,goodNumber就因该值为最少为1,所以默认的初值为1)
代码片段:
for(var i=0;i<this.data.shopCarStore.length;i++){
if (app.appGoodInfo.goodInfo.pro_id == this.data.shopCarStore[i].pro_id){
this.data.shopCarStore[i].goodNumber = this.data.shopCarStore[i].goodNumber+1;
isFind = true;
}else{
console.log("没找到pro_id");
isFind = false;
}
}
if (isFind == false ) {
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
}else{
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
添加变量isFind的目的是确认遍历结果,如果找到pro_id,isFind终值为true,反之为false,为false时就追加该数据到shopCarStore中。
虽然思路清楚,但在实际代码操作过程中有很多细节要注意,比如是否找到的判断,是不能放在for循环中,自己在写的过程中在这块走了很多弯路,如果放在里面会出现第二次添加没有在购物车中的数据时goodNubmer成倍增加的情况。第三次添加相同的数据时,本应该要的效果是goodNumber数值加1,不添加新数据,但是也能添加进去,而且goodNumber变为原来有两倍,归根结底是for循环第一次没找到时就添加数据,一旦添加成功,原本循环的条件(数组长度就会立即边长+1),本没有循环就会有第二次循环,这个一直让我很奇怪,这就导致第二次循环时,或发现找到了pro_id,原本的1就会变成2
错误的写法情况有一下两种:
// 第一种错误写法
var isFind = false;
for(var i=0;i<this.data.shopCarStore.length;i++){
if (app.appGoodInfo.goodInfo.pro_id == this.data.shopCarStore[i].pro_id){
this.data.shopCarStore[i].goodNumber = this.data.shopCarStore[i].goodNumber+1;
isFind = true;
}else{
console.log("没找到pro_id");
isFind = false;
//点击加入购物车后,将app.appGoodInfo.goodInfo追加数组shopCarStore中
}
if (isFind == false ) {
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
}
// 第二种错误写法,这种写法的错误结果和上述相同, for(var i=0;i<this.data.shopCarStore.length;i++){
if(app.appGoodInfo.goodInfo.pro_id== this.data.shopCarStore[i].pro_id){
this.data.shopCarStore[i].goodNumber = this.data.shopCarStore[i].goodNumber+1;
}else{
this.data.shopCarStore.push(app.appGoodInfo.goodInfo);
}
}
总结了下:原因还是for循环的原因,不可能总是第一次循环就能找到pro_id,一定要for循环变量结束才能判断,如果找到就goodNumber+1,反之追加数据
2.2、给购物车添加复选框按钮,点击或取消复选框时,可自动计算总价。
这里利用了复选框的响应事件bindchange=“checkboxChange”,在相对应的事件中可console.log(e),获得所需要的数据,
该功能那实现的思路是:
A、将该商品的一些属性:pro_id(唯一标识),price(价格),goodNumber(该商品在购物车中的数量),添加到数组money[]中
B、添加依据是:利用check的属性value,若value不为空,表示用户选中了,则添加该数据,若value为空,表示没有没有选中,需要判断该数据是否在money数组中(money[]的作用计算用户选中的商品的总价钱),原因是用户可能先选中了,这样就添加进了数组中,然后又点击了取消选中,所以就不能将该数据添加进数组,要删除。
C、最后将money储存在本地,储存的作用是为后面在选中的情况下,用户点击增加或减少商品时实时计算价格做准备。
具体可参考如下shopCar.js代码
// shopCar.wxml
<scroll-view scroll-y="true" style="height:568px">
<checkbox-group bindchange="checkboxChange" id="{{item.pro_id}}" data-index="{{index}}" data-goodNumber="{{item.goodNumber}}" data-price="{{item.pro_price}}" data-isCheck="{{isChecked}}" wx:for="{{shopCarStore}}">
<view class='good'>
<checkbox value="{{item.pro_id}}" class="choose"/>
<view class='store'>
<image src='../../Image/store.png'></image>
<text class="title">{{item.pro_name}}</text>
<button catchtap='deleCollect' data-index="{{index}}">删除该收藏</button>
</view>
<view class='info'>
<image src='{{item.pro_img}}'></image>
<text class='desc'>{{item.pro_desc}}</text>
<text class='location'>货源地>>{{item.pro_address}}</text>
<text class='price'>¥{{item.pro_price}}</text>
</view>
<view class='number'>
<image class='bigdes' src='../../Image/bigdes.png' bindtap="reduceNumber" data-index="{{index}}" value="{{item.pro_price}}"></image>
<text class='numtext'>{{item.goodNumber}}</text>
<image src='../../Image/bigadd.png' class='bigadd' bindtap="addNumber" bin data-index="{{index}}" ></image>
</view>
</view>
</checkbox-group>
<view class='total' style="position: fixed; bottom:0;">
<view class='total1'>
<text>合计:¥{{totalMoney}}</text>
</view>
<view class='topay'>
<text>去结算</text>
</view>
</view>
</scroll-view>
// shopCar.js
// 复选框响应事件
checkboxChange:function(e){
console.log(e);
var that = this;
var pro_id = e.currentTarget.id;
var checked = e.currentTarget.dataset.price;
checked = true;
if (e.detail.value!=''){
this.data.info = { price: e.currentTarget.dataset.price, pro_id: e.currentTarget.id, goodNumber: e.currentTarget.dataset.goodnumber, isChecked: checked};
this.data.money.push(this.data.info);
wx.setStorage({
key: 'money',
data: this.data.money,
})
}else{
this.data.isChecked = false;
for(var i = 0;i<this.data.money.length;i++){
if (pro_id == this.data.money[i].pro_id){
this.removeById(this.data.money,i);
wx.setStorage({
key: 'money',
data: this.data.money,
})
}
}
}
this.sum(); // 调用了求和的方法
},
// money求和运算 , 计算总价格
sum:function(){
var sum = 0;
if (this.data.money.length!=0){
for (var i = 0; i < this.data.money.length; i++) {
sum = sum + (this.data.money[i].price)*(this.data.money[i].goodNumber);
}
this.setData({ totalMoney: sum });
}else{
this.setData({ totalMoney: 0 });
}
},
感悟总结:这块用了两种方法,第一种方法是走了不少弯路,原因是自己对value值的利用不得当,虽然最终也做出来了,效果没有上述的方便明了,哈哈哈。可能是为第二种方法铺路。
2.3、当在复选框选中的情况下,可点击增加或减少某商品的数量,并实时计算商品总价。
实现思路:首先点击按钮增加或减少的实质是通过index值,更改在本地储存购物车数据shopCatStore中index相对应的行数据中的goodNumber,并调用this.onShow实时显示,要注意的是:
A、 对更改的shopCarStorep[]数据要及时保存,不然即便调用onShow方法也会出错。
B、 调用onshow方法的前提是:onshow方法中有对应显示功能的代码,本处实际上就是从本地获得shopCarStore,并显示。
这里加了一个前提条件:“在复选框选中的情况下”,所以就要用到前面提到的存到本地数组money,实际上,一旦能添加到money中,就说明该数据已选中,只需更改money[]中的goodNumber值即可。需要注意的还是对money[]的实时保存
代码如下:
// 控制商品数的数量
addNumber:function(e){
console.log(e);
var that = this;
var index = e.currentTarget.dataset.index;
(this.data.shopCarStore[index].goodNumber)++;
wx.setStorage({
key: 'shopCarStore',
data: that.data.shopCarStore,
success:function(){
that.onShow();
wx.getStorage({
key: 'money',
success: function (res) {
that.setData({ money: res.data });
for (var i = 0; i < that.data.money.length; i++) {
if (that.data.shopCarStore[index].pro_id==that.data.money[i].pro_id) {
(that.data.money[i].goodNumber)++ ;
}
}
that.sum();
wx.setStorage({
key: 'money',
data: that.data.money,
})
},
})
}
})
},
// 减少商品时对应的方法
reduceNumber:function(e){
console.log(e);
var that = this;
var index = e.currentTarget.dataset.index;
if (this.data.shopCarStore[index].goodNumber>1){
(this.data.shopCarStore[index].goodNumber)--;
}else{
this.data.shopCarStore[index].goodNumber = 1;
}
wx.setStorage({
key: 'shopCarStore',
data: that.data.shopCarStore,
success: function () {
that.onShow();
wx.getStorage({
key: 'money',
success: function (res) {
that.setData({ money: res.data });
for (var i = 0; i < that.data.money.length; i++) {
if (that.data.shopCarStore[index].pro_id == that.data.money[i].pro_id) {
(that.data.money[i].goodNumber)--;
}
}
that.sum();
wx.setStorage({
key: 'money',
data: that.data.money,
})
},
})
}
})
},
2.4、可管理购物车,如删除操作。
实现思路:思路很简单,还是依据当前点击所在的index,寻找在shopCarStore对应的index ,并删除,删除借用了自定义方法removeById(),需要注意的还是对曹锁后的shopCarStore的实时保存,否则一旦涉及到shopCarStore的获取都不是最新数据。
代码如下:
// 删除收藏
deleCollect:function(e){
console.log(e);
var index = e.currentTarget.dataset.index;
var that = this;
wx.showModal({
title: '提示',
content: '是否确认删除?',
success: function (res) {
if(res.confirm){
console.log("用户点击了确认");
wx.getStorage({
key: 'shopCarStore',
success: function (res) {
that.setData({ temp_shopCarStore: res.data });
// 根据点击的索引值删除数组中相对应的数据
that.removeById(that.data.temp_shopCarStore, index);
wx.setStorage({
key: 'shopCarStore',
data: that.data.temp_shopCarStore,
success: function () {
wx.showToast({
title: '删除成功',
icon: "success",
duration: 2000
})
// 调用生命周期函数的目的是为了能让更新后的数据及时显示
that.onShow();
}
})
},
})
}else{
console.log("用户点击了取消");
}
}
})
},