这个小例子是学习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 } ] }