渲染页面
静态结构
<template>
<view class="cart">
<!-- 1 列表 -->
<view class="cart-list">
<view class="cart-item">
<!-- 1 复选框 -->
<view class="goods-chk">
<u-checkbox value="" shape="circle" active-color="red"></u-checkbox>
</view>
<!-- 2 图片 -->
<view class="goods-img">
<u-image width="191rpx" height="191rpx"></u-image>
</view>
<!-- 3 信息 -->
<view class="goods-info">
<!-- 名称 -->
<view class="goods-name u-line-2"></view>
<!-- 价格和数量 -->
<view class="goods-price-num">
<view class="goods-price">¥xxx</view>
<view class="goods-num-tool">
<view class="num-btn">-</view>
<view class="goods-num">xxx</view>
<view class="num-btn">+</view>
</view>
</view>
</view>
</view>
</view>
<!-- 2 统计 -->
<view class="statistics">
<view class="all-chk">
<u-checkbox shape="circle" active-color="red">全选</u-checkbox>
</view>
<view class="all-price"> 合计: <text>¥xxx</text> </view>
<view class="all-count">
<u-button type="error" shape="circle">去结算(xxx)</u-button>
</view>
</view>
</view>
</template>
<script>
export default {};
</script>
<style lang="scss">
.cart {
padding-bottom: 111rpx;
.cart-list {
.cart-item {
display: flex;
padding: 10rpx;
border-bottom: 1rpx solid #ccc;
.goods-chk {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.goods-img {
flex: 2;
display: flex;
align-items: center;
justify-content: center;
}
.goods-info {
color: #666;
flex: 3;
display: flex;
flex-direction: column;
justify-content: space-around;
.goods-name {
}
.goods-price-num {
display: flex;
justify-content: space-between;
.goods-price {
color: #eb4450;
}
.goods-num-tool {
width: 140rpx;
height: 40rpx;
display: flex;
justify-content: space-between;
.num-btn {
border: 1rpx solid #ccc;
border-radius: 50%;
width: 40rpx;
height: 40rpx;
text-align: center;
line-height: 40rpx;
}
}
}
}
}
}
.statistics {
position: fixed;
background-color: #fff;
bottom: 0;
left: 0;
width: 100%;
z-index: 100;
border-top: 1rpx solid #ccc;
display: flex;
align-items: center;
padding: 15rpx;
.all-chk {
}
.all-price {
flex: 1;
color: #666;
text {
}
}
.all-count {
}
}
}
</style>
渲染数据
使用
mapState
辅助函数来获取商品数据
复选框这里不能直接v-modle,会双向绑定,造成数据修改
vuex 规定 修改state入口只能是mutations
u-checkbox
组件可以使用value绑定选中
<template>
<view class="cart">
<!-- 1 列表 -->
<view class="cart-list" v-for="item in goodsArr" :key="item.goods_id">
<view class="cart-item">
<!-- 1 复选框 -->
<view class="goods-chk" >
<u-checkbox
:value="item.checked"
shape="circle"
active-color="red"
></u-checkbox>
</view>
<!-- 2 图片 -->
<view class="goods-img">
<u-image :src="item.goods_small_logo" width="191rpx" height="191rpx"></u-image>
</view>
<!-- 3 信息 -->
<view class="goods-info">
<!-- 名称 -->
<view class="goods-name u-line-2">{{item.goods_name}}</view>
<!-- 价格和数量 -->
<view class="goods-price-num">
<view class="goods-price">¥{{item.goods_price}}</view>
<view class="goods-num-tool">
<view class="num-btn">-</view>
<view class="goods-num">{{item.count}}</view>
<view class="num-btn">+</view>
</view>
</view>
</view>
</view>
</view>
<!-- 2 统计 -->
<view class="statistics">
<view class="all-chk">
<u-checkbox shape="circle" active-color="red">全选</u-checkbox>
</view>
<view class="all-price"> 合计: <text>¥xxx</text> </view>
<view class="all-count">
<u-button type="error" shape="circle">去结算(xxx)</u-button>
</view>
</view>
</view>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
...mapState('cart',['goodsArr'])
},
};
</script>
功能
商品选择按钮
用户点击后,传递商品id给回调函数,提交mutations利用id来查找商品元素
<!-- 1 复选框 -->
<view class="goods-chk" >
<u-checkbox
:value="item.checked"
shape="circle"
active-color="red"
@change="handleItemChecked(item.goods_id)"
></u-checkbox>
</view>
<script>
import {mapState,mapMutations} from 'vuex'
export default {
methods: {
...mapMutations('cart',['cartGoodsCheckMutations']),
handleItemChecked(goods_id) {
// console.log(goods_id);
this.cartGoodsCheckMutations({goods_id})
}
},
computed: {
...mapState('cart',['goodsArr'])
},
};
</script>
// 单选
cartGoodsCheckMutations(state,payload) {
const goods = state.goodsArr.find(item => item.goods_id === payload.goods_id)
// console.log('当前商品项',goods);
// 取反
goods.checked = !goods.checked
// 修改数据之后都需要存储
uni.setStorageSync('cart',state.goodsArr)
}
加减功能
绑定同一个事件,但是传递的参数不一样 加传递1 减传递-1
<!-- 价格和数量 -->
<view class="goods-price-num">
<view class="goods-price">¥{{item.goods_price}}</view>
<view class="goods-num-tool">
<view class="num-btn" @click="handleGoodsItemCount(item.goods_id,-1)">-</view>
<view class="goods-num">{{item.count}}</view>
<view class="num-btn" @click="handleGoodsItemCount(item.goods_id,1)">+</view>
</view>
</view>
<script>
import {mapState,mapMutations} from 'vuex'
export default {
methods: {
...mapMutations('cart',['cartGoodsCheckMutations','cartGoodsCountMutations']),
// 数量加减
handleGoodsItemCount(goods_id,unit) {
this.cartGoodsCountMutations({goods_id,unit})
}
}
};
</script>
// 商品数量加减
cartGoodsCountMutations (state,payload) {
// 获取当前商品项
const goods = state.goodsArr.find(item => item.goods_id === payload.goods_id)
// unit值 1 或者 -1
goods.count += payload.unit
// 修改数据之后都需要存储
uni.setStorageSync('cart',state.goodsArr)
}
删除功能
当商品数量为0 的时候 弹窗询问 是否删除 是删除该商品 否关闭弹窗
uni.showModal({})
返回值中confirm
的值为true表示点击确定,以此来作为用户点击的判断
<view
class="num-btn"
@click="handleGoodsItemCount(item.goods_id, -1, item.count)"
>-</view>
<view class="goods-num">{{ item.count }}</view>
<view
class="num-btn"
@click="handleGoodsItemCount(item.goods_id, 1, item.count)"
>+</view>
// 数量加减
async handleGoodsItemCount (goods_id, unit, count) {
// 判断 是否点击的是 - 且 商品数量为1
if (unit === -1 && count === 1) {
const [err, { confirm }] = await uni.showModal({
title: '提示',
content: '是否删除该商品',
showCancel: true,
cancelText: "取消",
cancelColor: "#000000",
confirmText: "确定",
confirmColor: "#3CC51F",
})
if (confirm) {
// 用户点击确认后
this.cartGoodsDelete({ goods_id })
} else {
// 用户点击取消后
return
}
} else {
// 正常做数量编辑
this.cartGoodsCountMutations({ goods_id, unit })
}
},
// 商品删除
cartGoodsDelete (state, payload) {
const index = state.goodsArr.findIndex(item => item.goods_id === payload.goods_id)
state.goodsArr.splice(index, 1)
// 修改数据之后都需要存储
uni.setStorageSync('cart', state.goodsArr)
}