当前位置:   article > 正文

11、微信小程序——购物车_微信小程序购物车demo

微信小程序购物车demo

目录

1、代码分析

1.1  dom结构分析

1.2  全选控制反选

1.3  反选控制全选

1.4、计算总价

1.4 加、减

2、效果、代码演示 

1、代码分析

1.1  dom结构分析

购物车的组件结构主要由两部分组成:多选框部分( checkbox-group ) + 全选框部分( view )

1.2  全选控制反选

业务逻辑:

1、全选框(选中)——》 多选框(选中)、全选框(不选中)——》 多选框(不选中)

2、令复选框跟随全选框的状态变化——遍历数据,设置每条数据的 isChecked 状态

注意:因为无法直接操作数据,所以需要先行拷贝数据,再对其进行遍历(在本项目中,所有需要对数据进行遍历、筛选操作的步骤,都需要先拷贝数据)

  1. allChecked(e){
  2. console.log(e); //触发点击事件,拿到全选框的事件源对象
  3. // 全选框: 状态为 true时,令其为 false,当状态为 false时,令其状态变为 true
  4. if(this.data.isAllChecked){
  5. // 遍历数据,令复选框的状态跟随全选框变化
  6. // 拷贝数据、遍历数据
  7. let goodslist=JSON.parse(JSON.stringify(this.data.goods))
  8. goodslist.forEach(item=>item.isChecked=false)
  9. this.setData({
  10. isAllChecked:false,
  11. goods:goodslist //重新渲染
  12. })
  13. }else{
  14. let goodslist=JSON.parse(JSON.stringify(this.data.goods))
  15. goodslist.forEach(item=>item.isChecked=true)
  16. this.setData({
  17. isAllChecked:true,
  18. goods:goodslist
  19. })
  20. }
  21. },

1.3  反选控制全选

业务逻辑:

1、多选框(全部选中)——》全选框(选中)

因为复选框有多个,全选框只有一个,所以多选框控制全选框被选中的前提是确定每一个多选框都被选中了  ,打印复选框的事件源对象,发现复选框有一 detail.value 属性,可显示 复选框为 true 的对象 / 数量。所以当 e.detail.value.length===this.data.goods.length 时,表示复选框都被选中了

 2、多选框(有一不选中)——》全选框(不选中)

遍历数据( forEach ) 并 检查元素 ( includes ),如果 e.detail.value 中包含 数据id,则令该复选框的 isChecked=true,否则为 false

  1. // 单选控制全选
  2. changeCound(e) {
  3. console.log(e);
  4. let checkedArr = e.detail.value
  5. if (checkedArr.length == this.data.goods.length) {
  6. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  7. goodsList.forEach(item => item.isChecked = true)
  8. this.setData({
  9. isAllChecked: true,
  10. goods: goodsList
  11. })
  12. } else {
  13. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  14. goodsList.forEach(item => {
  15. if (checkedArr.includes(item.id)) {
  16. item.isChecked = true
  17. } else {
  18. item.isChecked = false
  19. }
  20. })
  21. this.setData({
  22. isAllChecked: false,
  23. goods: goodsList
  24. })
  25. }
  26. },

1.4、计算总价

通常用 reduce 来计算总价,其中 total 表示旧值,item表示新值,0为初始值

. reduce( ( total , item ) => { } , 0 )

  1. // 计算总价
  2. computedTotalPrice() {
  3. let totalPrice = this.data.goods.reduce((total, item) => {
  4. if (item.isChecked) {
  5. return total + item.num * item.price
  6. } else {
  7. return total
  8. }
  9. }, 0)
  10. this.setData({
  11. totalPrice: totalPrice
  12. })
  13. },

1.4 加、减

  1. // 加、减、删除
  2. handle: function (e) {
  3. let id = e.currentTarget.dataset.id
  4. console.log(id);
  5. var index = e.currentTarget.dataset.index
  6. var val = `goods[${index}].num` //对数据对象 goods 中的 num 属性进行修改
  7. let oldnum = this.data.goods.find(item => item.id == id).num //查找
  8. console.log(oldnum);
  9. // 减
  10. if (e.currentTarget.dataset.name == "mulse") {
  11. let newNum = oldnum - 1
  12. if (newNum > 0) {
  13. this.setData({
  14. [val]: newNum
  15. })
  16. }else if(newNum == 0){
  17. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  18. let newGoodList=goodsList.filter(item=>item.id!==id)
  19. this.setData({
  20. goods:newGoodList
  21. })
  22. }
  23. // 加
  24. }else if(e.currentTarget.dataset.name=="add"){
  25. let newnum=++oldnum
  26. this.setData({
  27. [val]:newnum
  28. })
  29. }
  30. // 删除
  31. else if (e.currentTarget.dataset.name == "del") {
  32. let goodslist = JSON.parse(JSON.stringify(this.data.lists))
  33. let newLists = goodslist.filter(item => item.id !== id)
  34. this.setData({
  35. lists: newLists
  36. })
  37. }
  38. this.computedTotalPrice()
  39. }
  40. })

2、代码演示 

 index.wxml:

  1. <checkbox-group bindchange="changeCound" class="top">
  2. <view wx:for="{{goods}}" wx:key="id" class="checkbox">
  3. <view class="chleft">
  4. <checkbox value="{{item.id}}" checked="{{item.isChecked}}" class="cleft"></checkbox>
  5. <image src="{{item.imgUrl}}" mode="" class="pic" />
  6. </view>
  7. <view class="Box">
  8. <view class="box-left">
  9. <text class="name">{{item.name}}</text>
  10. <text class="price">¥{{item.price}}</text>
  11. </view>
  12. <view class="box-right">
  13. <text bindtap="handle" data-id="{{item.id}}" data-name="mulse" data-index="{{index}}">-</text>
  14. <text>{{item.num}}</text>
  15. <text bindtap="handle" data-id="{{item.id}}" data-name="add" data-index="{{index}}">+</text>
  16. <text bindtap="handle" class="del">x</text>
  17. </view>
  18. </view>
  19. </view>
  20. </checkbox-group>
  21. <view class="bottom">
  22. <view class="bottom-box" bindtap="allChecked">
  23. <label>
  24. <checkbox value="" checked="{{isAllChecked}}" />
  25. <text>全选</text>
  26. </label>
  27. </view>
  28. <view class="total">
  29. {{totalPrice}} 元
  30. </view>
  31. </view>

index.scss

  1. .top {
  2. height:90vh;
  3. overflow: auto;
  4. .checkbox {
  5. position: relative;
  6. width: 100vw;
  7. height: 100px;
  8. border: 1px solid #eee;
  9. display: flex;
  10. flex-direction: row;
  11. .chleft{
  12. display: flex;
  13. flex-direction: row;
  14. align-content: center;
  15. width: 41%;
  16. .cleft {
  17. margin-left: 10px;
  18. margin-right: 10px;
  19. line-height: 100px;
  20. }
  21. .pic {
  22. width:80px;
  23. height: 80px;
  24. margin-top: 10px;
  25. object-fit: cover;
  26. }
  27. }
  28. .Box{
  29. width: 59%;
  30. height: 100%;
  31. background-color: #fff;
  32. .box-left{
  33. position: relative;
  34. width: 100%;
  35. height: 50%;
  36. text{
  37. position: relative;
  38. width:50px;
  39. height: 20px;
  40. margin-left: 10px;
  41. }
  42. .name{
  43. position: absolute;
  44. top:20rpx;
  45. left:5rpx;
  46. }
  47. .price{
  48. position: absolute;
  49. top:20rpx;
  50. right:5rpx;
  51. text-align: left;
  52. }
  53. }
  54. .box-right{
  55. position: relative;
  56. margin-top: 17px;
  57. >text{
  58. width: 20px;
  59. margin-left: 10px;
  60. font-weight: bolder;
  61. }
  62. .del{
  63. position: absolute;
  64. top:-2px;
  65. right: 10px;
  66. margin-left: 100px;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. .bottom{
  73. position: fixed;
  74. bottom: 0;
  75. left:0;
  76. width: 100%;
  77. height: 11vh;
  78. box-shadow: 5px 5px 5px 5px rgb(204, 204, 204);
  79. line-height: 11vh;
  80. display: flex;
  81. flex-direction: row;
  82. .bottom-box{
  83. width: 50%;
  84. margin-left: 10px;
  85. }
  86. .total{
  87. width: 50%;
  88. text-align: right;
  89. padding-right: 15px;
  90. }
  91. }

index.js

  1. Page({
  2. data: {
  3. goods: [
  4. {
  5. id: '1',
  6. name: '黄桃',
  7. num: 10,
  8. price: 10,
  9. isChecked: false,
  10. imgUrl: '/images/HT.jpg'
  11. },
  12. {
  13. id: '2',
  14. name: '西瓜',
  15. num: 20,
  16. price: 8,
  17. isChecked: true,
  18. imgUrl: '/images/XG.jpg'
  19. },
  20. {
  21. id: '3',
  22. name: '猕猴桃',
  23. num: 6,
  24. price: 12,
  25. isChecked: false,
  26. imgUrl: '/images/MHT.jpg'
  27. }
  28. ],
  29. isAllChecked: false,
  30. totalPrice: 0
  31. },
  32. onLoad() {
  33. this.computedTotalPrice()
  34. },
  35. // 单选控制全选
  36. changeCound(e) {
  37. console.log(e);
  38. let checkedArr = e.detail.value
  39. if (checkedArr.length == this.data.goods.length) {
  40. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  41. goodsList.forEach(item => item.isChecked = true)
  42. this.setData({
  43. isAllChecked: true,
  44. goods: goodsList
  45. })
  46. } else {
  47. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  48. goodsList.forEach(item => {
  49. if (checkedArr.includes(item.id)) {
  50. item.isChecked = true
  51. } else {
  52. item.isChecked = false
  53. }
  54. })
  55. this.setData({
  56. isAllChecked: false,
  57. goods: goodsList
  58. })
  59. }
  60. this.computedTotalPrice()
  61. },
  62. // 全选控制单选
  63. allChecked(e) {
  64. if (this.data.isAllChecked) {
  65. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  66. goodsList.forEach(item => item.isChecked = false) //这里是赋值
  67. this.setData({
  68. isAllChecked: false,
  69. goods: goodsList
  70. })
  71. } else {
  72. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  73. goodsList.forEach(item => item.isChecked = true) //这里是赋值
  74. this.setData({
  75. isAllChecked: true,
  76. goods: goodsList
  77. })
  78. }
  79. this.computedTotalPrice()
  80. },
  81. // 计算总价
  82. computedTotalPrice() {
  83. let totalPrice = this.data.goods.reduce((total, item) => {
  84. if (item.isChecked) {
  85. return total + item.num * item.price
  86. } else {
  87. return total
  88. }
  89. }, 0)
  90. this.setData({
  91. totalPrice: totalPrice
  92. })
  93. },
  94. // 加、减、删除
  95. handle: function (e) {
  96. let id = e.currentTarget.dataset.id
  97. console.log(id);
  98. var index = e.currentTarget.dataset.index
  99. var val = `goods[${index}].num`
  100. let oldnum = this.data.goods.find(item => item.id == id).num
  101. console.log(oldnum);
  102. if (e.currentTarget.dataset.name == "mulse") {
  103. let newNum = oldnum - 1
  104. if (newNum > 0) {
  105. this.setData({
  106. [val]: newNum
  107. })
  108. }else if(newNum == 0){
  109. let goodsList = JSON.parse(JSON.stringify(this.data.goods))
  110. let newGoodList=goodsList.filter(item=>item.id!==id)
  111. this.setData({
  112. goods:newGoodList
  113. })
  114. }
  115. }else if(e.currentTarget.dataset.name=="add"){
  116. let newnum=++oldnum
  117. this.setData({
  118. [val]:newnum
  119. })
  120. }
  121. this.computedTotalPrice()
  122. }
  123. })

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/517142
推荐阅读
  

闽ICP备14008679号