【 uniapp - 黑马优购 | 购物车页面(3)】结算页面组件封装与渲染 (超详细代码讲解)

简介: 【 uniapp - 黑马优购 | 购物车页面(3)】结算页面组件封装与渲染 (超详细代码讲解)

9.3 结算区域

9.3.1 把结算区域封装为组件

  1. components 目录中,新建 my-settle 结算组件:

  1. 初始化 my-settle 组件的基本结构和样式:
<template>
  <!-- 最外层的容器 -->
  <view class="my-settle-container">
    结算组件
  </view>
</template>
<script>
export default {
  data() {
    return {}
  },
}
</script>
<style lang="scss">
.my-settle-container {
  /* 底部固定定位 */
  position: fixed;
  bottom: 0;
  left: 0;
  /* 设置宽高和背景色 */
  width: 100%;
  height: 50px;
  background-color: cyan;
}
</style>
  1. cart.vue 页面中使用自定义的 my-settle 组件,并美化页面样式,防止页面底部被覆盖:
<template>
  <view class="cart-container">
    <!-- 使用自定义的 address 组件 -->
    <!-- 购物车商品列表的标题区域 -->
    <!-- 商品列表区域 -->
    <!-- 结算区域 -->
    <my-settle></my-settle>
  </view>
</template>
<style lang="scss">
.cart-container {
  padding-bottom: 50px;
}
</style>

9.3.2 渲染结算区域的结构和样式

  1. 定义如下的 UI 结构:
<!-- 最外层的容器 -->
<view class="my-settle-container">
  <!-- 全选区域 -->
  <label class="radio">
    <radio color="#C00000" :checked="true" /><text>全选</text>
  </label>
  <!-- 合计区域 -->
  <view class="amount-box">
    合计:<text class="amount">¥1234.00</text>
  </view>
  <!-- 结算按钮 -->
  <view class="btn-settle">结算(0)</view>
</view>
  1. 美化样式:
.my-settle-container {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 50px;
  // 将背景色从 cyan 改为 white
  background-color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 5px;
  font-size: 14px;
  .radio {
    display: flex;
    align-items: center;
  }
  .amount {
    color: #c00000;
  }
  .btn-settle {
    height: 50px;
    min-width: 100px;
    background-color: #c00000;
    color: white;
    line-height: 50px;
    text-align: center;
    padding: 0 10px;
  }
}

9.3.3 动态渲染已勾选商品的总数量

  1. store/cart.js 模块中,定义一个名称为 checkedCountgetters,用来统计已勾选商品的总数量:
// 勾选的商品的总数量
checkedCount(state) {
  // 先使用 filter 方法,从购物车中过滤器已勾选的商品
  // 再使用 reduce 方法,将已勾选的商品总数量进行累加
  // reduce() 的返回值就是已勾选的商品的总数量
  return state.cart.filter(x => x.goods_state).reduce((total, item) => total += item.goods_count, 0)
}
  1. my-settle 组件中,通过 mapGetters 辅助函数,将需要的 getters 映射到当前组件中使用:
import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters('m_cart', ['checkedCount']),
  },
  data() {
    return {}
  },
}
  1. checkedCount 的值渲染到页面中:
<!-- 结算按钮 -->
<view class="btn-settle">结算({{checkedCount}})</view>

9.3.4 动态渲染全选按钮的选中状态

  1. 使用 mapGetters 辅助函数,将商品的总数量映射到当前组件中使用,并定义一个叫做 isFullCheck 的计算属性:
import { mapGetters } from 'vuex'
export default {
  computed: {
    // 1. 将 total 映射到当前组件中
    ...mapGetters('m_cart', ['checkedCount', 'total']),
    // 2. 是否全选
    isFullCheck() {
      return this.total === this.checkedCount
    },
  },
  data() {
    return {}
  },
}
  1. radio 组件动态绑定 checked 属性的值:
<!-- 全选区域 -->
<label class="radio">
  <radio color="#C00000" :checked="isFullCheck" /><text>全选</text>
</label>

9.3.5 实现商品的全选/反选功能

  1. store/cart.js 模块中,定义一个叫做 updateAllGoodsStatemutations 方法,用来修改所有商品的勾选状态:
// 更新所有商品的勾选状态
updateAllGoodsState(state, newState) {
  // 循环更新购物车中每件商品的勾选状态
  state.cart.forEach(x => x.goods_state = newState)
  // 持久化存储到本地
  this.commit('m_cart/saveToStorage')
}
  1. my-settle 组件中,通过 mapMutations 辅助函数,将需要的 mutations 方法映射到当前组件中使用:
// 1. 按需导入 mapMutations 辅助函数
import { mapGetters, mapMutations } from 'vuex'
export default {
  // 省略其它代码
  methods: {
    // 2. 使用 mapMutations 辅助函数,把 m_cart 模块提供的 updateAllGoodsState 方法映射到当前组件中使用
    ...mapMutations('m_cart', ['updateAllGoodsState']),
  },
}
  1. UI 中的 label 组件绑定 click 事件处理函数:
<!-- 全选区域 -->
<label class="radio" @click="changeAllState">
  <radio color="#C00000" :checked="isFullCheck" /><text>全选</text>
</label>
在 my-settle 组件的 methods 节点中,声明 changeAllState 事件处理函数:
methods: {
  ...mapMutations('m_cart', ['updateAllGoodsState']),
  // label 的点击事件处理函数
  changeAllState() {
    // 修改购物车中所有商品的选中状态
    // !this.isFullCheck 表示:当前全选按钮的状态取反之后,就是最新的勾选状态
    this.updateAllGoodsState(!this.isFullCheck)
  }
}

9.3.6 动态渲染已勾选商品的总价格

  1. store/cart.js 模块中,定义一个叫做 checkedGoodsAmountgetters,用来统计已勾选商品的总价格:
// 已勾选的商品的总价
checkedGoodsAmount(state) {
  // 先使用 filter 方法,从购物车中过滤器已勾选的商品
  // 再使用 reduce 方法,将已勾选的商品数量 * 单价之后,进行累加
  // reduce() 的返回值就是已勾选的商品的总价
  // 最后调用 toFixed(2) 方法,保留两位小数
  return state.cart.filter(x => x.goods_state)
                   .reduce((total, item) => total += item.goods_count * item.goods_price, 0)
                   .toFixed(2)
}
  1. my-settle 组件中,使用 mapGetters 辅助函数,把需要的 checkedGoodsAmount 映射到当前组件中使用:
...mapGetters('m_cart', ['total', 'checkedCount', 'checkedGoodsAmount'])
  1. 在组件的 UI 结构中,渲染已勾选的商品的总价:
<!-- 合计区域 -->
<view class="amount-box">
  合计:<text class="amount">¥{{checkedGoodsAmount}}</text>
</view>

9.3.7 动态计算购物车徽标的数值

1. 问题说明:当修改购物车中商品的数量之后,tabBar 上的数字徽标不会自动更新。

2. 解决方案:改造 mixins/tabbar-badge.js 中的代码,使用 watch 侦听器,监听 total 总数量的变化,从而动态为 tabBar 的徽标赋值:

import { mapGetters } from 'vuex'
// 导出一个 mixin 对象
export default {
  computed: {
    ...mapGetters('m_cart', ['total']),
  },
  watch: {
    // 监听 total 值的变化
    total() {
      // 调用 methods 中的 setBadge 方法,重新为 tabBar 的数字徽章赋值
      this.setBadge()
    },
  },
  onShow() {
    // 在页面刚展示的时候,设置数字徽标
    this.setBadge()
  },
  methods: {
    setBadge() {
      // 调用 uni.setTabBarBadge() 方法,为购物车设置右上角的徽标
      uni.setTabBarBadge({
        index: 2,
        text: this.total + '', // 注意:text 的值必须是字符串,不能是数字
      })
    },
  },
}

9.3.8 渲染购物车为空时的页面结构

  1. 资料 目录中的 cart_empty@2x.png 图片复制到项目的 /static/ 目录中
  2. 改造 cart.vue 页面的 UI 结构,使用 v-ifv-else 控制购物车区域和空白购物车区域的按需展示:
<template>
  <view class="cart-container" v-if="cart.length !== 0">
    <!-- 使用自定义的 address 组件 -->
    <!-- 购物车商品列表的标题区域 -->
    <!-- 商品列表区域 -->
    <!-- 结算区域 -->
  </view>
  <!-- 空白购物车区域 -->
  <view class="empty-cart" v-else>
    <image src="/static/cart_empty@2x.png" class="empty-img"></image>
    <text class="tip-text">空空如也~</text>
  </view>
</template>
  1. 美化空白购物车区域的样式:
.empty-cart {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 150px;
  .empty-img {
    width: 90px;
    height: 90px;
  }
  .tip-text {
    font-size: 12px;
    color: gray;
    margin-top: 15px;
  }
}

9.4 分支的合并与提交

  1. cart 分支进行本地提交:
git add .
git commit -m "完成了购物车的开发"
  1. 将本地的 cart 分支推送到码云:
git push -u origin cart
  1. 将本地 cart 分支中的代码合并到 master 分支:
git checkout master
git merge cart
git push
  1. 删除本地的 cart 分支:
git branch -d cart

三连支持一下!



目录
相关文章
|
4天前
|
SQL 开发框架 数据库连接
uniapp中sqlite数据库常用操作的简单封装
uniapp中sqlite数据库常用操作的简单封装
|
4天前
|
移动开发 前端开发 JavaScript
uniapp中IO模块(管理本地文件系统)的常用功能封装
uniapp中IO模块(管理本地文件系统)的常用功能封装
|
4天前
|
开发框架 JSON 定位技术
uniapp中map组件动态加载marks标记
uniapp中map组件动态加载marks标记
|
4天前
|
JavaScript 前端开发 小程序
uniapp中nvue页面如何全屏,map组件如何全屏?
uniapp中nvue页面如何全屏,map组件如何全屏?
|
5天前
|
移动开发 小程序 Android开发
基于jeecgboot的flowable为uniapp适配的流程页面调整
基于jeecgboot的flowable为uniapp适配的流程页面调整
12 0
|
5天前
|
资源调度
uniapp引入vant组件库
uniapp引入vant组件库
26 11
|
5天前
|
移动开发 小程序 API
uniapp中组件库Mask 遮罩层 的使用方法
uniapp中组件库Mask 遮罩层 的使用方法
16 1
|
5天前
|
移动开发 小程序 API
uniapp组件库Card 卡片 的使用方法
uniapp组件库Card 卡片 的使用方法
15 1
|
5天前
|
移动开发 小程序 API
uniapp组件库Line 线条 的适用方法
uniapp组件库Line 线条 的适用方法
15 0
|
5天前
|
移动开发 小程序 iOS开发
uniapp组件库fullScreen 压窗屏的适用方法
uniapp组件库fullScreen 压窗屏的适用方法
17 1

热门文章

最新文章