uinapp项目+vue3+pinia,将商品加入购物车
先写一个商品卡片组件
<template>
<view class="nb-card" >
<view class="shopping_box">
<view v-if="isSelect">
<checkbox-group @change="radioChange">
<label>
<checkbox color="#e4020e" :value="item" style="border-radius: 50%;" value="cb" :checked="checkedSelect"/>
</label>
</checkbox-group>
</view>
<view>
<image style="width: 100px; height: 100px;border-radius: 10px"
:src="item.cover"></image>
</view>
<view class="right" >
<view class="title">
{{ item?.title }}
</view>
<view class="description">任选2-3杯~具体饮品温度请备注~</view>
<view class="discount" >
<view >限时特价</view>
</view>
<view style="margin-top: 10px">
<view style="display: flex;justify-content: space-between;width: 100%">
<view>
<text style="font-size: 12px">¥</text>
<text style="font-size: 16px">{{ item.minPrice }}</text>
</view>
<view class="addOrDelete">
<view class="my-circle" @click.stop="delete_shopping">-</view>
<view style="border: 1px blue;width: 30px" @click.stop="">
<text>{{ commoditySize(item.id) }}</text>
</view>
<view class="my-circle" @click.stop="add_shopping">+</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import {ref} from "vue";
import {useCommodityStore} from "@/store/modules/CommodityStore";
const emits = defineEmits(['click'])
const props = withDefaults(defineProps<{
treeTagId?: string,
item?: any,
isSelect?: Boolean,
}>(), {
treeTagId: "",
item: {
title: "6666",
cover: "https://img2.baidu.com/it/u=3088885732,2641299430&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
minPrice: "999",
isSelect: false,
id: ""
}
})
const commodity = useCommodityStore()
function goClick() {
emits('click')
}
async function add_shopping() {
await commodity.joinChart({id: props.item.id, action: "up"})
const data = commodity.getInfo(props.item.id)
}
function commoditySize(id: any) {
const data = commodity.getInfo(id)
return data?.size || 0
}
function delete_shopping() {
commodity.joinChart({id: props.item.id, action: "down"})
}
const checkedSelect = ref<boolean>(false)
async function radioChange(value: any) {
checkedSelect.value = !checkedSelect.value
console.log(value.detail.value, commoditySize(props.item.id));
if (checkedSelect.value) {
const info = useCommodityStore().info;
info[props.item.id].flag = true;
} else {
const info = useCommodityStore().info;
info[props.item.id].flag = false;
}
}
</script>
<style scoped lang="scss">
.shopping_box {
display: flex;
justify-content: space-between;
align-items: center;
text-align: center;
}
.right {
flex: 1 1 auto;
height: 100%;
margin-left: 10px;
justify-content: space-between;
flex-direction: column;
}
.my-circle {
border: 1px solid;
border-radius: 50%;
height: 20px;
width: 20px;
line-height: 15px;
text-align: center;
background-color: #e4020e;
color: #fff;
}
.title {
font-size: 14px;
text-align: left;
color: #393939;
font-weight: 1000;
font-family: 宋体;
}
.description {
text-align: start;
font-size: 10px;
color: #a9a9a9;
margin-top: 8px;
}
.discount {
display:flex;
margin-top: 8px;
&>view{
padding: 5px 10px;
font-size: 10px;
color: #a9a9a9;
border: #df5e62 1px solid;
border-radius: 3px;
}
}
.addOrDelete {
display: flex;
margin-right: 10px;
background-color: #f3f4f6;
border-radius: 30px;
}
</style>
先定义一个pinia缓存
import {defineStore} from "pinia";
export const commodityStore = defineStore('commodity', {
state: (): {
info: {
[key: string]: {
id: string
size: number
}
}
} => ({
info: {}
}),
getters: {},
actions: {
joinChart(data: {
id: string,
action: 'up' | 'down'
}) {
if (!this.info[data.id]) {
this.info[data.id] = {
id: data.id,
size: 0
}
}
if (data.action === 'up') {
this.info[data.id].size++
} else {
this.info[data.id].size--
}
if (this.info[data.id].size <= 0) {
delete this.info[data.id]
}
this.info = {
...this.info
}
},
getInfo(id: any) {
return this.info[id]
},
getInfoList():Object{
return this.info
}
}
})
将商品加入缓存的部分 (卡片里面已经包含此部分)
async function add_shopping() {
await commodity.joinChart({id: props.item.id, action: "up"})
const data = commodity.getInfo(props.item.id)
}
function delete_shopping() {
commodity.joinChart({id: props.item.id, action: "down"})
}
在购物车中给购物车加入选择(卡片里面已经包含此部分)
<view v-if="isSelect">
<checkbox-group @change="radioChange">
<label>
<checkbox color="#e4020e" :value="item" style="border-radius: 50%;" value="cb" :checked="checkedSelect"/>
</label>
</checkbox-group>
</view>
const checkedSelect = ref<boolean>(false)
async function radioChange(value: any) {
checkedSelect.value = !checkedSelect.value
console.log(value.detail.value, commoditySize(props.item.id));
if (checkedSelect.value) {
const info = useCommodityStore().info;
info[props.item.id].flag = true;
} else {
const info = useCommodityStore().info;
info[props.item.id].flag = false;
}
}
我们在引用组件的页面写一个apiSubmit事件---去结算
const list = ref<ShoppingCartItem[]>([])
async function apiSubmit() {
const _list = list.value.filter(o => o.flag);
const form = {
list: _list.map(o => {
return {
id: o.id,
size: o.size
}
})
}
const {data} = await commodityApi.commodity.torderCreate({
...form
})
form1.value.value = data.totalPrice
await apiPayment(data.torderId)
}