vue3 + pinia实现简单购物车功能
这个小例子是学习vue3与pinia状态管理工具时写的一个简单的购物车功能,
它实现了从模拟接口(node.js的json-server提供)读取商品数据,到添加商品到购物车和购物车中删除商品等购物车主要功能
准备工作,执行 npm i pinia -G 安装pinia
执行 npm json-server 安装node.js的json工具
执行 json-server ./src/data/api.json -p 9000 //运行定义好的json文件 及访问端口


"pinia": "^2.0.22",
"vue": "^3.2.37",
<template>
<div>
<h1>产品列表</h1>
<hr>
<ul>
<li v-for="item,index in producets" class="shop-box">
<div><img :src="IphoneImg"/></div>
<div>{{item.name}} -- ¥{{item.price}} 库存:{{item.inventory}}</div>
<div><button @click="addToCart(item)" :disabled="item.inventory <= 0">加入购物车</button></div>
</li>
</ul>
<Cart></Cart>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import IphoneImg from '../../../public/vite.svg'
import {storeToRefs} from 'pinia'
import Cart from './Cart.vue'
import useProducetStore from '@/store/producetStore';
import useCartStore from '@/store/cartStore'
const producetStore = useProducetStore()
const { producets } = storeToRefs(producetStore)
const {addToCart} = useCartStore()
onMounted(()=>{
producetStore.loadData()
})
</script>
<style lang="css">
.shop-box{
}
.shop-box div{
display: inline;
margin: 0 10px;
}
</style>
<template>
<div v-if="cartList.length > 0 && cartStore.toAllPrice > 0">
<h2>购物车</h2>
<hr>
<ul>
<template v-for="item in cartList">
<li v-if="item.quantity >= 1" class="car-shop">
{{item.name}} ¥{{item.price}} x <button @click="reduceToCartClick(item)" :disabled="item.quantity < 1">-</button><input type="number" :value="item.quantity" @input="handlechange" /><button @click="addToCartClick(item)" :disabled="item.inventory <= 0">+</button> = ¥{{item.price * item.quantity}}
</li>
</template>
</ul>
<hr>
<h4 class="all">总价:¥{{cartStore.toAllPrice}}</h4>
</div>
</template>
<script setup>
import {storeToRefs} from 'pinia'
import useCartStore from '@/store/cartStore';
import useProducetStore from '@/store/producetStore';
const producetStore = useProducetStore()
const { producets } = storeToRefs(producetStore)
const cartStore = useCartStore()
const { addToCart, reduceToCart } = useCartStore()
const {cartList} = storeToRefs(cartStore)
const handlechange = (e)=>{
// console.log('--->',e.target.value)
}
const reduceToCartClick = (p)=>{
reduceToCart(p)
producetStore.updateProduces(p)
}
const addToCartClick = (p) =>{
addToCart(p)
producetStore.updateProduces(p)
}
</script>
<style lang="css">
.car-shop{
}
.car-shop button{
margin: 0 5px;
cursor: pointer;
}
.all{
text-align: right;
color: red;
}
</style>
import { defineStore } from "pinia";
import axios from 'axios'
const useProducetStore = defineStore('producetStore', {
state() {
return {
producets: []
}
},
actions: {
async loadData() {
//安装一个node服务工具来模拟接口功能 //npm i json-server -g
//json-server查看工具命令
//json-server ./src/data/api.json -p 9000 //运行定义好的json文件 及访问端口
//http://localhost:9000/data 浏览器中通过该地址访问定义好的json数据
let result = await axios.get('http://localhost:9000/data')
// console.log('data---->', result.data)
this.producets = result.data
// axios.post('http://localhost:9000/data', '{id: 5, name: "iphone15", price: 1200,inventory:2}')
//json-server服务可以通过post请求向json插入一条数据,但每次个性json数据后需求重启服务才能更新页面数据
},
updateProduces(producet) {
const p = this.producets.find((item)=>{
return item.id === producet.id
})
if(p){
p.inventory = producet.inventory
}
}
}
})
export default useProducetStore
import {defineStore} from 'pinia'
const useCartStore = defineStore('cartStore', {
state() {
return {
cartList: []
}
},
actions: {
addToCart(producet){
// console.log('producet--->', producet)
const p = this.cartList.find((item)=>{
return item.id === producet.id
})
if(p){
p.quantity ++
const cartProduct = producet.hasOwnProperty('quantity')
if (!cartProduct) {
p.inventory --
}
} else {
let inventory = producet.inventory
inventory --
this.cartList.push({
...producet,
inventory: inventory,
quantity: 1 //购物车里商品数量+1
})
}
producet.inventory --
},
reduceToCart(producet){
// console.log('reduce--->', producet)
const p = this.cartList.find((item)=>{
return item.id === producet.id
})
if(p){
p.quantity --
p.inventory ++
if (p.quantity < 1) {
let newCartList = new Set(this.cartList)
newCartList.delete(producet)
this.cartList = [...newCartList]
}
}
}
},
getters: { //pinia的计算属性
toAllPrice(){
return this.cartList.reduce((sum, item)=>{
sum += item.price * item.quantity
return sum
},0)
}
}
})
export default useCartStore
{ "data": [ { "id": 1, "name": "iphone11", "price": 3000, "inventory": 3 }, { "id": 2, "name": "iphone12", "price": 5000, "inventory": 3 }, { "id": 3, "name": "iphone13", "price": 8000, "inventory": 6 }, { "id": 4, "name": "iphone14", "price": 10000, "inventory": 2 } ] }

浙公网安备 33010602011771号