(6). 为 my-goods 组件封装 NumberBox
- 修改 my-goods.vue 组件的源代码,在类名为 goods-info-box 的 view 组件内部渲染 NumberBox 组件的基本结构:
<uni-number-box :min="1"></uni-number-box>
2. 美化样式
.goods-item-right { display: flex; flex: 1; flex-direction: column; justify-content: space-between; .goods-name { font-size: 13px; } .goods-info-box { display: flex; align-items: center; justify-content: space-between; } .goods-price { font-size: 16px; color: #c00000; } }
- 在 my-goods.vue 组件中,动态为 NumberBox 组件绑定商品的数量值:
<view class="goods-info-box"> <!-- 商品价格 --> <view class="goods-price">¥{{goods.goods_price | tofixed}}</view> <!-- 商品数量 --> <uni-number-box :min="1" :value="goods.goods_count"></uni-number-box> </view>
- 控制NumberBox的显示与隐藏
直接复用radios的
<!-- 计算框 --> <uni-number-box :min="1" :value="item.goods_count" v-show="showRadio"></uni-number-box> showRadio: { type: Boolean, default: false }
(7).为 my-goods 组件封装 num-change 事件
- 先在父组件声明自定义事件 (cart.vue)
<!-- 绑定自定义事件 --> <my-goods :item="item" :showRadio="true" @radioChange="radioChangeHandler" @numChange="numberChangeHandler"></my-goods>
numberChangeHandler(e) { console.log('yyyy->', e) }
- 在子组件声明触发事件 (my-goods.vue)
<!-- 计算框 --> <uni-number-box :min="1" :value="item.goods_count" v-show="showRadio" @change="numChangeHandler"></uni-number-box>
// 计数器 -> 触发就会传过来改变后的值 numChangeHandler(val) { // 传递数量和id this.$emit('numChange', { goods_id: this.item.goods_id, // 要转换成数字 goods_count: val - 0 }) }
- 永久化存储:在
store/cart.js
模块中,声明如下的 mutations 方法,用来修改对应商品的数量:
// 更新购物车中商品的数量 updateGoodsCount(state, goods) { // 根据 goods_id 查询购物车中对应商品的信息对象 const findResult = state.cart.find(x => x.goods_id === goods.goods_id) if(findResult) { // 更新对应商品的数量 findResult.goods_count = goods.goods_count // 持久化存储到本地 this.commit('m_cart/saveToStorage') } }
在 cart.vue
页面中,通过 mapMutations 这个辅助函数,将需要的 mutations 方法映射到当前页面中使用:
import badgeMix from '@/mixins/tabbar-badge.js' import { mapState, mapMutations } from 'vuex' export default { mixins: [badgeMix], computed: { ...mapState('m_cart', ['cart']), }, data() { return {} }, methods: { ...mapMutations('m_cart', ['updateGoodsState', 'updateGoodsCount']), // 商品的勾选状态发生了变化 radioChangeHandler(e) { this.updateGoodsState(e) }, // 商品的数量发生了变化 numberChangeHandler(e) { this.updateGoodsCount(e) }, }, }
- 优化购物车上的数量与新增新减同步
mixins/tabbar.js
import { mapGetters } from "vuex" export default { onShow() { this.setBadge() }, watch: { total: { handler(val) { uni.setTabBarBadge({ // 0索引是 : 首页 1索引是分类 2索引是购物车 3索引是我的 index: 2, text: val + '' }) }, immediate: true } }, // 声明 computed: { ...mapGetters('m_cart', ['total']) }, methods: { setBadge() { uni.setTabBarBadge({ // 0索引是 : 首页 1索引是分类 2索引是购物车 3索引是我的 index: 2, text: this.total + '' }) } } }
(8).渲染滑动删除的 UI 效果
滑动删除需要用到 uni-ui 的 uni-swipe-action 组件和 uni-swipe-action-item。详细的官方文档请参考SwipeAction 滑动操作。
- 改造
cart.vue
页面的 UI 结构,将商品列表区域的结构修改如下(可以使用uSwipeAction
代码块快速生成基本的 UI 结构):
<!-- 左滑删除购物信息 --> <uni-swipe-action> <!-- 循环渲染购物车中的数据 --> <block v-for="(item,index) in cart" :key="index"> <uni-swipe-action-item :right-options="options" @click=""> <!-- 绑定自定义事件 --> <my-goods :item="item" :showRadio="true" @radioChange="radioChangeHandler" @numChange="numberChangeHandler"></my-goods> </uni-swipe-action-item> </block> </uni-swipe-action>
data() { return { options: [{ text: '删除', style: { backgroundColor: '#C00000' } }] }; },
(9).实现滑动删除的功能
- 在 store/cart.js 模块的 mutations 节点中声明如下的方法,从而根据商品的 Id 从购物车中移除对应的商品:
// 左滑删除 removeGoodsById(state, item) { // 调用数组的 filter 方法进行过滤 state.cart = state.cart.filter(x => x.goods_id !== item.goods_id) // 通过commit方法,调用 m_cart命名空间下的saveToStorage this.commit('m_cart/saveToStorage') }, // 持久化存储本地数据 saveToStorage(state) { uni.setStorageSync('cart', JSON.stringify(state.cart)) },
- 在 cart.vue 页面中,使用 mapMutations 辅助函数,把需要的方法映射到当前页面中使用:
<!-- 左滑删除购物信息 --> <uni-swipe-action> <!-- 循环渲染购物车中的数据 --> <block v-for="(item,index) in cart" :key="index"> <uni-swipe-action-item :right-options="options" @click="swiperItemHandler(item)"> <!-- 绑定自定义事件 --> <my-goods :item="item" :showRadio="true" @radioChange="radioChangeHandler" @numChange="numberChangeHandler"></my-goods> </uni-swipe-action-item> </block> </uni-swipe-action>
methods: { ...mapMutations('m_cart', ['updateGoodsState']), ...mapMutations('m_cart', ['updateGoodsNumber']), ...mapMutations('m_cart', ['removeGoodsById']), // 更改选中状态 radioChangeHandler(e) { console.log('xxxx->', e) this.updateGoodsState(e) }, // 更改数字 numberChangeHandler(e) { console.log('yyyy->', e) this.updateGoodsNumber(e) }, // 删除指定项目 swiperItemHandler(e) { console.log('eeee>', e) this.removeGoodsById(e) } }