微信小程序 购物车简单实例

微信小程序,这里实现购物车功能的小demo,有需要此功能的朋友可以参考下。

摘要: 加减商品数量,汇总价格,全选与全不选

设计思路:

一、从网络上传入以下Json数据格式的数组 1.购物车id:cid 2.标题title 3.数量num 4.图片地址 5.价格price 6.小计 7.是否选中selected

二、点击复选框toggle操作 如已经选中的,经点击变成未选中,反之而反之 点击依据index作为标识,而不用cid,方便遍历

三、全选操作 首次点击即为全部选中,再次点击为全不选,全选按钮本身也跟随toggle变换

四、点击结算按钮,将已选中的cid数组取出,以供通过网络提交到服务端,这里给个toast作为结果演示。

五、利用stepper作加减运算,同样依据index作为标识,点完写回num值。

六、布局,全选与结算按钮底部对齐,购物车商城自适应高度,类似于Android的weight。

步骤:

初始数据渲染

1.1 布局与样式表

上方是一个商品列表,下方是一个全选按钮与立即结算按钮

商品列表左部为商品缩略图,右上为商品标题,右下为商品价格与数量,其中商品数量使用WXStepper来实现加减操作

js:初始化一个数据源,这往往是从网络获取的,相关接口可参见:https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html

?
1
2
3
4
5
6
7
8
9
10
11
Page({
   data:{
     carts: [
       {cid:1008,title:'Zippo打火机',image:'https://img12.360buyimg.com/n7/jfs/t2584/348/1423193442/572601/ae464607/573d5eb3N45589898.jpg',num:'1',price:'198.0',sum:'198.0',selected:true},
       {cid:1012,title:'iPhone7 Plus',image:'https://img13.360buyimg.com/n7/jfs/t3235/100/1618018440/139400/44fd706e/57d11c33N5cd57490.jpg',num:'1',price:'7188.0',sum:'7188.0',selected:true},
       {cid:1031,title:'得力订书机',image:'https://img10.360buyimg.com/n7/jfs/t2005/172/380624319/93846/b51b5345/5604bc5eN956aa615.jpg',num:'3',price:'15.0',sum:'45.0',selected:false},
       {cid:1054,title:'康师傅妙芙蛋糕',image:'https://img14.360buyimg.com/n7/jfs/t2614/323/914471624/300618/d60b89b6/572af106Nea021684.jpg',num:'2',price:'15.2',sum:'30.4',selected:false},
       {cid:1063,title:'英雄钢笔',image:'https://img10.360buyimg.com/n7/jfs/t1636/60/1264801432/53355/bb6a3fd1/55c180ddNbe50ad4a.jpg',num:'1',price:'122.0',sum:'122.0',selected:true},
     ]
   }
})

布局文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< view class = "container carts-list" >
   < view wx:for = "{{carts}}" class = "carts-item" data-title = "{{item.title}}" data-url = "{{item.url}}" bindtap = "bindViewTap" >
     < view >
      < image class = "carts-image" src = "{{item.image}}" mode = "aspectFill" />
     </ view >
    < view class = "carts-text" >
     < text class = "carts-title" >{{item.title}}</ text >
     < view class = "carts-subtitle" >
      < text class = "carts-price" >{{item.sum}}</ text >
      < text >WXStepper</ text >
     </ view >
    </ view >
   </ view >
</ view >

样式表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*外部容器*/
.container {
   display : flex;
   flex- direction : column;
   align-items: center ;
   justify- content : space-between;
   box-sizing: border-box;
}
 
/*整体列表*/
.carts-list {
   display : flex;
   flex- direction : column;
   padding : 20 rpx 40 rpx;
}
 
/*每行单元格*/
.carts-item {
   display : flex;
   flex- direction : row;
   height : 150 rpx;
   /*width属性解决标题文字太短而缩略图偏移*/
   width : 100% ;
   border-bottom : 1px solid #eee ;
   padding : 30 rpx 0 ;
}
 
/*左部图片*/
.carts-image {
   width : 150 rpx;
   height : 150 rpx;
}
 
 
/*右部描述*/
.carts-text {
   width : 100% ;
   display : flex;
   flex- direction : column;
   justify- content : space-between;
}
 
/*右上部分标题*/
.carts-title {
   margin : 10 rpx;
   font-size : 30 rpx;
}
 
/*右下部分价格与数量*/
.carts-subtitle {
   font-size : 25 rpx;
   color :darkgray;
   padding : 0 20 rpx;
   display : flex;
   flex- direction : row;
   justify- content :space-between;
}
 
/*价格*/
.carts-price {
   color : #f60 ;
}

1.2 集成WXStepper

1.2.1 复制组件内容

[2016-10-16]

将stepper.wxss的内容复制到cart.wxss中

将stepper.wxml的内容复制到cart.wxml中

与之前的单一组件不同的是:这里要定义数组minusStatuses来与每一个加减按钮相应。当然,合并入carts也是没问题的。

        minusStatuses: ['disabled', 'disabled', 'normal', 'normal', 'disabled']

原来的静态字符WXStepper换成以下的代码

?
1
2
3
4
5
6
7
8
<view class= "stepper" >
        <!-- 减号 -->
        <text class= "{{minusStatuses[index]}}" data-index= "{{index}}" bindtap= "bindMinus" >-</text>
        <!-- 数值 -->
        <input type= "number" bindchange= "bindManual" value= "{{item.num}}" />
        <!-- 加号 -->
        <text class= "normal" data-index= "{{index}}" bindtap= "bindPlus" >+</text>
       </view>

js代码bindMinus、bindPlus分别改造为如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
bindMinus: function (e) {
     var index = parseInt(e.currentTarget.dataset.index);
     var num = this .data.carts[index].num;
     // 如果只有1件了,就不允许再减了
     if (num > 1) {
       num --;
     }
     // 只有大于一件的时候,才能normal状态,否则disable状态
     var minusStatus = num <= 1 ? 'disabled' : 'normal' ;
     // 购物车数据
     var carts = this .data.carts;
     carts[index].num = num;
     // 按钮可用状态
     var minusStatuses = this .data.minusStatuses;
     minusStatuses[index] = minusStatus;
     // 将数值与状态写回
     this .setData({
       carts: carts,
       minusStatuses: minusStatuses
     });
   },
   bindPlus: function (e) {
     var index = parseInt(e.currentTarget.dataset.index);
     var num = this .data.carts[index].num;
     // 自增
     num ++;
     // 只有大于一件的时候,才能normal状态,否则disable状态
     var minusStatus = num <= 1 ? 'disabled' : 'normal' ;
     // 购物车数据
     var carts = this .data.carts;
     carts[index].num = num;
     // 按钮可用状态
     var minusStatuses = this .data.minusStatuses;
     minusStatuses[index] = minusStatus;
     // 将数值与状态写回
     this .setData({
       carts: carts,
       minusStatuses: minusStatuses
     });
   },

效果如图:

[2016-10-17]

修正手工改动数量保存到数组

1.3 集成LXCheckboxGroup

复制布局文件代码到wxml,这里需要判断一下已选状态,一般购物车勾选状态是记录在网络的。

index值用于传值js,遍历之用。

      

?
1
2
3
<!-- 复选框图标 -->
    < icon wx:if = "{{item.selected}}" type = "success_circle" size = "20" bindtap = "bindCheckbox" data-index = "{{index}}" />
    < icon wx:else type = "circle" size = "20" bindtap = "bindCheckbox" data-index = "{{index}}" />

复选框居中

?
1
2
3
4
5
/*复选框样式*/
.carts-list icon {
   margin-top: 60rpx;
   margin-right: 20rpx;
}

绑定点击复选框事件,对选择状态做反选操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bindCheckbox: function (e) {
   /*绑定点击事件,将checkbox样式改变为选中与非选中*/
   //拿到下标值,以在carts作遍历指示用
   var index = parseInt(e.currentTarget.dataset.index);
   //原始的icon状态
   var selected = this .data.carts[index].selected;
   var carts = this .data.carts;
   // 对勾选状态取反
   carts[index].selected = !selected;
   // 写回经点击修改后的数组
   this .setData({
     carts: carts
   });
}

效果图:

1.4 加入全选与立即结算按钮

1.4.1 修改布局文件,实现上述按钮底部对齐,使用flex与固定高度来完成。

减少为3行,看是否还在最底;此外,还要保证悬浮在底部,不被列表项的滚动而滚动。

?
1
2
3
4
5
6
7
8
<view class= "carts-footer" >
    <view bindtap= "bindSelectAll" >
      <icon wx: if = "{{selectedAllStatus}}" type= "success_circle" size= "20" />
      <icon wx: else type= "circle" size= "20" />
      <text>全选</text>
    </view>
    <view class= "button" >立即结算</view>
  </view>

之前用<button>立即结算</button>来实现,发现无论如何都不能实现全选部件与结算按钮分散对齐,不响应如下样式

?
1
2
3
display: flex;
flex-direction: row;
justify-content: space-between;

样式表

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*底部按钮*/
.carts-footer {
   width: 100%;
   height: 80rpx;
   display: flex;
   flex-direction: row;
   justify-content: space-between;
}
 
/*复选框*/
.carts-footer icon {
   margin-left: 20rpx;
}
 
/*全选字样*/
.carts-footer text {
   font-size: 30rpx;
   margin-left: 8rpx;
   line-height: 10rpx;
}
 
/*立即结算按钮*/
.carts-footer .button {
   line-height: 80rpx;
   text-align: center;
   width:220rpx;
   height: 80rpx;
   background-color: #f60;
   color: white;
   font-size: 36rpx;
   border-radius: 0;
   border: 0;
}

1.4.2 全选与全不选事件

实现bindSelectAll事件,改变全选状态

首先定义一个data值,以记录全选状态

selectedAllStatus: false

事件实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bindSelectAll: function () {
    // 环境中目前已选状态
    var selectedAllStatus = this .data.selectedAllStatus;
    // 取反操作
    selectedAllStatus = !selectedAllStatus;
    // 购物车数据,关键是处理selected值
    var carts = this .data.carts;
    // 遍历
    for ( var i = 0; i < carts.length; i++) {
      carts[i].selected = selectedAllStatus;
    }
    this .setData({
      selectedAllStatus: selectedAllStatus,
      carts: carts
    });
  }

1.4.3 立即结算显示目前所选的cid,以供提交到网络,商品数量应该是包括在cid中的,后端设计应该只关注cid与uid

布局文件也埋一下toast,js只要改变toast的显示与否即可。

?
1
2
3
< toast hidden = "{{toastHidden}}" bindchange = "bindToastChange" >
   {{toastStr}}
</ toast >

为立即结算绑定事件bindCheckout,弹出cid弹窗

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bindCheckout: function () {
    // 初始化toastStr字符串
    var toastStr = 'cid:' ;
    // 遍历取出已勾选的cid
    for ( var i = 0; i < this .data.carts.length; i++) {
      if ( this .data.carts[i].selected) {
        toastStr += this .data.carts[i].cid;
        toastStr += ' ' ;
      }
    }
    //存回data
    this .setData({
      toastHidden: false ,
      toastStr: toastStr
    });
  },
  bindToastChange: function () {
    this .setData({
      toastHidden: true
    });
  }

1.5 底部悬浮固定

1.5.1 商品列表 .carts-list 加入 margin-bottom: 80rpx; 以及修改上边距为零,使得底部部件与分隔不重复出现,padding: 0 40rpx;

1.5.2 底部按钮 .carts-footer 加入 background: white;

1.5.3 .carts-footer 加入

?
1
2
3
position: fixed;
bottom: 0;
border-top: 1px solid #eee;

1.6 汇总

1.6.1 首先定义一个数据源,并在布局文件中埋坑

total: ''

<text>{{total}}</text>

1.6.2 通用汇总函数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
sum: function () {
     var carts = this .data.carts;
     // 计算总金额
     var total = 0;
     for ( var i = 0; i < carts.length; i++) {
       if (carts[i].selected) {
         total += carts[i].num * carts[i].price;
       }
     }
     // 写回经点击修改后的数组
     this .setData({
       carts: carts,
       total: '¥' + total
     });
   }

然后分别在bindMinus bindPlus bindCheckbox bindSelectAll onLoad中调用this.sum()

如图:

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

参考地址:http://www.jb51.net/article/95563.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值