渲染页面

静态结构

  1. <template>
  2. <view class="cart">
  3. <!-- 1 列表 -->
  4. <view class="cart-list">
  5. <view class="cart-item">
  6. <!-- 1 复选框 -->
  7. <view class="goods-chk">
  8. <u-checkbox value="" shape="circle" active-color="red"></u-checkbox>
  9. </view>
  10. <!-- 2 图片 -->
  11. <view class="goods-img">
  12. <u-image width="191rpx" height="191rpx"></u-image>
  13. </view>
  14. <!-- 3 信息 -->
  15. <view class="goods-info">
  16. <!-- 名称 -->
  17. <view class="goods-name u-line-2"></view>
  18. <!-- 价格和数量 -->
  19. <view class="goods-price-num">
  20. <view class="goods-price">¥xxx</view>
  21. <view class="goods-num-tool">
  22. <view class="num-btn">-</view>
  23. <view class="goods-num">xxx</view>
  24. <view class="num-btn">+</view>
  25. </view>
  26. </view>
  27. </view>
  28. </view>
  29. </view>
  30. <!-- 2 统计 -->
  31. <view class="statistics">
  32. <view class="all-chk">
  33. <u-checkbox shape="circle" active-color="red">全选</u-checkbox>
  34. </view>
  35. <view class="all-price"> 合计: <text>¥xxx</text> </view>
  36. <view class="all-count">
  37. <u-button type="error" shape="circle">去结算(xxx)</u-button>
  38. </view>
  39. </view>
  40. </view>
  41. </template>
  42. <script>
  43. export default {};
  44. </script>
  45. <style lang="scss">
  46. .cart {
  47. padding-bottom: 111rpx;
  48. .cart-list {
  49. .cart-item {
  50. display: flex;
  51. padding: 10rpx;
  52. border-bottom: 1rpx solid #ccc;
  53. .goods-chk {
  54. flex: 1;
  55. display: flex;
  56. align-items: center;
  57. justify-content: center;
  58. }
  59. .goods-img {
  60. flex: 2;
  61. display: flex;
  62. align-items: center;
  63. justify-content: center;
  64. }
  65. .goods-info {
  66. color: #666;
  67. flex: 3;
  68. display: flex;
  69. flex-direction: column;
  70. justify-content: space-around;
  71. .goods-name {
  72. }
  73. .goods-price-num {
  74. display: flex;
  75. justify-content: space-between;
  76. .goods-price {
  77. color: #eb4450;
  78. }
  79. .goods-num-tool {
  80. width: 140rpx;
  81. height: 40rpx;
  82. display: flex;
  83. justify-content: space-between;
  84. .num-btn {
  85. border: 1rpx solid #ccc;
  86. border-radius: 50%;
  87. width: 40rpx;
  88. height: 40rpx;
  89. text-align: center;
  90. line-height: 40rpx;
  91. }
  92. }
  93. }
  94. }
  95. }
  96. }
  97. .statistics {
  98. position: fixed;
  99. background-color: #fff;
  100. bottom: 0;
  101. left: 0;
  102. width: 100%;
  103. z-index: 100;
  104. border-top: 1rpx solid #ccc;
  105. display: flex;
  106. align-items: center;
  107. padding: 15rpx;
  108. .all-chk {
  109. }
  110. .all-price {
  111. flex: 1;
  112. color: #666;
  113. text {
  114. }
  115. }
  116. .all-count {
  117. }
  118. }
  119. }
  120. </style>

渲染数据

使用mapState辅助函数来获取商品数据

复选框这里不能直接v-modle,会双向绑定,造成数据修改
vuex 规定 修改state入口只能是mutations

u-checkbox组件可以使用value绑定选中

  1. <template>
  2. <view class="cart">
  3. <!-- 1 列表 -->
  4. <view class="cart-list" v-for="item in goodsArr" :key="item.goods_id">
  5. <view class="cart-item">
  6. <!-- 1 复选框 -->
  7. <view class="goods-chk" >
  8. <u-checkbox
  9. :value="item.checked"
  10. shape="circle"
  11. active-color="red"
  12. ></u-checkbox>
  13. </view>
  14. <!-- 2 图片 -->
  15. <view class="goods-img">
  16. <u-image :src="item.goods_small_logo" width="191rpx" height="191rpx"></u-image>
  17. </view>
  18. <!-- 3 信息 -->
  19. <view class="goods-info">
  20. <!-- 名称 -->
  21. <view class="goods-name u-line-2">{{item.goods_name}}</view>
  22. <!-- 价格和数量 -->
  23. <view class="goods-price-num">
  24. <view class="goods-price">¥{{item.goods_price}}</view>
  25. <view class="goods-num-tool">
  26. <view class="num-btn">-</view>
  27. <view class="goods-num">{{item.count}}</view>
  28. <view class="num-btn">+</view>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. <!-- 2 统计 -->
  35. <view class="statistics">
  36. <view class="all-chk">
  37. <u-checkbox shape="circle" active-color="red">全选</u-checkbox>
  38. </view>
  39. <view class="all-price"> 合计: <text>¥xxx</text> </view>
  40. <view class="all-count">
  41. <u-button type="error" shape="circle">去结算(xxx)</u-button>
  42. </view>
  43. </view>
  44. </view>
  45. </template>
  46. <script>
  47. import {mapState} from 'vuex'
  48. export default {
  49. computed: {
  50. ...mapState('cart',['goodsArr'])
  51. },
  52. };
  53. </script>

功能

商品选择按钮

用户点击后,传递商品id给回调函数,提交mutations利用id来查找商品元素

  1. <!-- 1 复选框 -->
  2. <view class="goods-chk" >
  3. <u-checkbox
  4. :value="item.checked"
  5. shape="circle"
  6. active-color="red"
  7. @change="handleItemChecked(item.goods_id)"
  8. ></u-checkbox>
  9. </view>
  10. <script>
  11. import {mapState,mapMutations} from 'vuex'
  12. export default {
  13. methods: {
  14. ...mapMutations('cart',['cartGoodsCheckMutations']),
  15. handleItemChecked(goods_id) {
  16. // console.log(goods_id);
  17. this.cartGoodsCheckMutations({goods_id})
  18. }
  19. },
  20. computed: {
  21. ...mapState('cart',['goodsArr'])
  22. },
  23. };
  24. </script>
  1. // 单选
  2. cartGoodsCheckMutations(state,payload) {
  3. const goods = state.goodsArr.find(item => item.goods_id === payload.goods_id)
  4. // console.log('当前商品项',goods);
  5. // 取反
  6. goods.checked = !goods.checked
  7. // 修改数据之后都需要存储
  8. uni.setStorageSync('cart',state.goodsArr)
  9. }

加减功能

绑定同一个事件,但是传递的参数不一样 加传递1 减传递-1

  1. <!-- 价格和数量 -->
  2. <view class="goods-price-num">
  3. <view class="goods-price">¥{{item.goods_price}}</view>
  4. <view class="goods-num-tool">
  5. <view class="num-btn" @click="handleGoodsItemCount(item.goods_id,-1)">-</view>
  6. <view class="goods-num">{{item.count}}</view>
  7. <view class="num-btn" @click="handleGoodsItemCount(item.goods_id,1)">+</view>
  8. </view>
  9. </view>
  10. <script>
  11. import {mapState,mapMutations} from 'vuex'
  12. export default {
  13. methods: {
  14. ...mapMutations('cart',['cartGoodsCheckMutations','cartGoodsCountMutations']),
  15. // 数量加减
  16. handleGoodsItemCount(goods_id,unit) {
  17. this.cartGoodsCountMutations({goods_id,unit})
  18. }
  19. }
  20. };
  21. </script>
  1. // 商品数量加减
  2. cartGoodsCountMutations (state,payload) {
  3. // 获取当前商品项
  4. const goods = state.goodsArr.find(item => item.goods_id === payload.goods_id)
  5. // unit值 1 或者 -1
  6. goods.count += payload.unit
  7. // 修改数据之后都需要存储
  8. uni.setStorageSync('cart',state.goodsArr)
  9. }

删除功能

当商品数量为0 的时候 弹窗询问 是否删除 是删除该商品 否关闭弹窗

uni.showModal({})返回值中confirm的值为true表示点击确定,以此来作为用户点击的判断

  1. <view
  2. class="num-btn"
  3. @click="handleGoodsItemCount(item.goods_id, -1, item.count)"
  4. >-</view>
  5. <view class="goods-num">{{ item.count }}</view>
  6. <view
  7. class="num-btn"
  8. @click="handleGoodsItemCount(item.goods_id, 1, item.count)"
  9. >+</view>
  10. // 数量加减
  11. async handleGoodsItemCount (goods_id, unit, count) {
  12. // 判断 是否点击的是 - 且 商品数量为1
  13. if (unit === -1 && count === 1) {
  14. const [err, { confirm }] = await uni.showModal({
  15. title: '提示',
  16. content: '是否删除该商品',
  17. showCancel: true,
  18. cancelText: "取消",
  19. cancelColor: "#000000",
  20. confirmText: "确定",
  21. confirmColor: "#3CC51F",
  22. })
  23. if (confirm) {
  24. // 用户点击确认后
  25. this.cartGoodsDelete({ goods_id })
  26. } else {
  27. // 用户点击取消后
  28. return
  29. }
  30. } else {
  31. // 正常做数量编辑
  32. this.cartGoodsCountMutations({ goods_id, unit })
  33. }
  34. },
  1. // 商品删除
  2. cartGoodsDelete (state, payload) {
  3. const index = state.goodsArr.findIndex(item => item.goods_id === payload.goods_id)
  4. state.goodsArr.splice(index, 1)
  5. // 修改数据之后都需要存储
  6. uni.setStorageSync('cart', state.goodsArr)
  7. }