feature: 购物车完整demo

This commit is contained in:
WORK\cirry 2022-04-28 11:57:53 +08:00
parent ca37a1831f
commit 6dece8bccc
7 changed files with 155 additions and 16 deletions

0
public/product.json Normal file
View File

View File

@ -1,26 +1,18 @@
<template>
<HelloWorld/>
<product-page></product-page>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import HelloWorld from './components/HelloWorld.vue';
import { defineComponent } from "vue";
import ProductPage from './components/ProductPage.vue'
export default defineComponent({
name: 'App',
components: {
HelloWorld
ProductPage
}
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

35
src/api/shop.ts Normal file
View File

@ -0,0 +1,35 @@
export interface IProduct {
id: string
name: string
price: number
inventory: number
}
const _products: IProduct[] = [
{
"id": "0",
"name": "IPad Pro",
"price": 5999,
"inventory": 2
},
{
"id": "1",
"name": "IPhone 13 Pro",
"price": 7999,
"inventory": 3
}
]
export const getProducts = async () => {
await wait(1000)
return _products
}
export const buyProducts = async () => {
await wait(1000)
return Math.random() > 0.5
}
async function wait( delay: number ) {
return new Promise(( resolve ) => setTimeout(resolve, delay))
}

View File

@ -9,7 +9,7 @@
</template>
<script lang="ts" setup>
import { userMainStore } from "@/store";
import { storeToRefs } from "pinia";
import { storeToRefs } from 'pinia';
const mainStore = userMainStore()
console.log(mainStore.count)

View File

@ -0,0 +1,35 @@
<template>
<h2>Pinia 购物车示例</h2>
<hr>
<h3>商品列表</h3>
<ul>
<li v-for="item in productStore.all" :key="item.id">
<p>{{ item.name }} -- {{ item.price }} -- 库存{{ item.inventory }}</p>
<button :disabled="item.inventory===0" @click="cartStore.addProductToCart(item)">添加到购物车</button>
</li>
</ul>
<hr>
<h3>你的购物车</h3>
<ul>
<li v-for="item in cartStore.cartProducts" :key="item.id">
<p>{{ item.name }} -- 价格 {{ item.price }} x {{ item.quantity }}</p>
</li>
</ul>
<p>商品总价{{ cartStore.totalPrice }}</p>
<button @click="cartStore.checkout()">结算</button>
<p>{{ cartStore.checkStatus }}</p>
</template>
<script setup lang="ts">
import { useProductStore } from "@/store/product";
import { useCartStore } from "@/store/cart";
const productStore = useProductStore()
const cartStore = useCartStore()
productStore.loadAllProducts()
</script>
<style scoped>
</style>

57
src/store/cart.ts Normal file
View File

@ -0,0 +1,57 @@
import { defineStore } from "pinia";
import { buyProducts, IProduct } from "@/api/shop";
import { useProductStore } from "@/store/product";
type CartProduct = {
quantity: number
} & IProduct
enum checkoutStatus {
PENDING = "未结算",
SUCCESS = "结算成功",
FALSE = "结算失败"
}
export const useCartStore = defineStore('cart', {
state: () => ( {
cartProducts: [] as CartProduct[],
checkStatus: checkoutStatus.PENDING
} ),
getters: {
totalPrice( state ) {
return state.cartProducts.reduce(( pre, cur ) => {
return pre + cur.price * cur.quantity
}, 0)
}
},
actions: {
addProductToCart( product: IProduct ) {
if ( product.inventory < 1 ) {
return
}
const cartItem: CartProduct | undefined = this.cartProducts.find(item => item.id === product.id)
if ( cartItem ) {
cartItem.quantity++
} else {
this.cartProducts.push({
id: product.id,
name: product.name,
inventory: product.inventory,
price: product.price,
quantity: 1
})
}
const productStore = useProductStore()
productStore.decrementProductInventory(product)
},
async checkout() {
const result = await buyProducts()
if ( result ) {
this.checkStatus = checkoutStatus.SUCCESS
this.cartProducts = []
} else {
this.checkStatus = checkoutStatus.FALSE
}
}
}
})

20
src/store/product.ts Normal file
View File

@ -0,0 +1,20 @@
import { defineStore } from "pinia";
import { getProducts, IProduct } from "@/api/shop";
export const useProductStore = defineStore('product', {
state: () => ( {
all: [] as IProduct[]
} ),
getters: {},
actions: {
async loadAllProducts() {
this.all = await getProducts()
},
decrementProductInventory( product: IProduct ) {
const productItem = this.all.find(item => item.id === product.id)
if ( productItem ) {
productItem.inventory--
}
}
}
})