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
        }
    ]
}

 

posted @ 2022-10-14 15:48  知兮  阅读(1011)  评论(0编辑  收藏  举报