在 components
目录中,新建 my-settle
结算组件:
初始化
my-settle
组件的基本结构和样式:
结算组件
在 cart.vue
页面中使用自定义的 my-settle
组件,并美化页面样式,防止页面底部被覆盖:
渲染结算区域的结构和样式
定义如下的 UI 结构:
合计:¥1234.00 结算(0)
美化样式:
.my-settle-container {position: fixed;bottom: 0;left: 0;width: 100%;height: 50px;// 将背景色从 cyan 改为 whitebackground-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;}
}
动态渲染已勾选商品的总数量
在 store/cart.js
模块中,定义一个名称为 checkedCount
的 getters,用来统计已勾选商品的总数量:
// 勾选的商品的总数量
checkedCount(state) {// 先使用 filter 方法,从购物车中过滤器已勾选的商品// 再使用 reduce 方法,将已勾选的商品总数量进行累加// reduce() 的返回值就是已勾选的商品的总数量return state.cart.filter(x => x.goods_state).reduce((total, item) => total += item.goods_count, 0)
}
在 my-settle
组件中,通过 mapGetters
辅助函数,将需要的 getters 映射到当前组件中使用:
import { mapGetters } from 'vuex'export default {computed: {...mapGetters('m_cart', ['checkedCount']),},data() {return {}},
}
将 checkedCount
的值渲染到页面中:
结算({{checkedCount}})
动态渲染全选按钮的选中状态
使用 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 {}},
}
为 radio 组件动态绑定 checked
属性的值:
改造成功
实现商品的全选/反选功能
在 store/cart.js
模块中,定义一个叫做 updateAllGoodsState
的 mutations 方法,用来修改所有商品的勾选状态:
// 更新所有商品的勾选状态
updateAllGoodsState(state, newState) {// 循环更新购物车中每件商品的勾选状态state.cart.forEach(x => x.goods_state = newState)// 持久化存储到本地this.commit('m_cart/saveToStorage')
}
在 my-settle
组件中,通过 mapMutations
辅助函数,将需要的 mutations 方法映射到当前组件中使用:
// 1. 按需导入 mapMutations 辅助函数
import { mapGetters, mapMutations } from 'vuex'export default {// 省略其它代码methods: {// 2. 使用 mapMutations 辅助函数,把 m_cart 模块提供的 updateAllGoodsState 方法映射到当前组件中使用...mapMutations('m_cart', ['updateAllGoodsState']),},
}
为 UI 中的 label
组件绑定 click
事件处理函数:
在 my-settle
组件的 methods 节点中,声明 changeAllState
事件处理函数:
methods: {...mapMutations('m_cart', ['updateAllGoodsState']),// label 的点击事件处理函数changeAllState() {// 修改购物车中所有商品的选中状态// !this.isFullCheck 表示:当前全选按钮的状态取反之后,就是最新的勾选状态this.updateAllGoodsState(!this.isFullCheck)}
}
动态渲染已勾选商品的总价格
在 store/cart.js
模块中,定义一个叫做 checkedGoodsAmount
的 getters,用来统计已勾选商品的总价格:
// 已勾选的商品的总价
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)
}
在 my-settle
组件中,使用 mapGetters
辅助函数,把需要的 checkedGoodsAmount
映射到当前组件中使用:
...mapGetters('m_cart', ['total', 'checkedCount', 'checkedGoodsAmount'])
在组件的 UI 结构中,渲染已勾选的商品的总价:
合计:¥{{checkedGoodsAmount}}
动态计算购物车徽标的数值
问题说明:当修改购物车中商品的数量之后,tabBar 上的数字徽标不会自动更新。
解决方案:改造 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 的值必须是字符串,不能是数字})},},
}
渲染购物车为空时的页面结构
将 资料
目录中的 cart_empty@2x.png
图片复制到项目的 /static/
目录中
改造 cart.vue
页面的 UI 结构,使用 v-if
和 v-else
控制购物车区域和空白购物车区域的按需展示:
空空如也~
美化空白购物车区域的样式:
.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;}
}
将 cart
分支进行本地提交:
git add .
git commit -m "完成了购物车的开发"
将本地的 cart
分支推送到码云:
git push -u origin cart
将本地 cart
分支中的代码合并到 master
分支:
git checkout master
git merge cart
git push
删除本地的 cart
分支:
git branch -d cart
上一篇:A.构造(牛客挑战赛)
下一篇:GDKOI2023 普及组游记