pinia实战 购物车(自定义插件实现pinia持久化)

目录

一、实例

二、需求

三. 代码解析

shop.vue 

shop.ts

四、持久化插件

插件介绍

持久化实现思路


一、实例

二、需求

  •  单选全选功能,并且可以互相联动
  •  小计功能
  •  总计功能
  •  商品加减,数量为零时不能在减

三. 代码解析

shop.vue 

1.获取shop模块实例

2.updateNum实现商品加减函数

3.allSelectChange 实现全选函数

4.singChange实现单选函数

<template>
    <div>我是购物车</div>
    <div>全选 <input type="checkbox" v-model="ShopStore.isAllSelect" @change="allSelectChange"></div> 
    <div v-for="(item,index) in ShopStore.goods" :key="index">
    <input @change="singChange" v-model="item.select" type="checkbox" name="" id="">
    商品名:{{ item.name }}  ----
    商品价格:{{ item.price }}  ----
    <button @click="updateNum(index,1)">+</button>
    {{ item.num||1 }}
    <button @click="updateNum(index,-1)" >-</button>
    小记 {{ item.price*(item.num||1) }}
    </div>
    <div>总价:{{ ShopStore.total }}</div>
</template>
<script setup lang="ts">
import { userShopStore } from "./store/shop";
const ShopStore = userShopStore()
const updateNum = (index: number, num: number) => {
    ShopStore.updateNum(index,num)
}
const allSelectChange = () => {
    ShopStore.allSelectChange()
}
const singChange = () => {
    ShopStore.singChange()
}
</script>

shop.ts

导入 defineStore函数  interface 定义接口类  导出模块实例

state存放数据  goods商品数组实现接口 isAllSelect全选状态

getters 计算属性。通过filter过滤出选择项 reduce累加计算总计

actions 存放方法

        updateNum 加减操作 初始化num 进行数值操作

        allSelectChange 每次点击全选,都需要同步单选状态 控制全选

        singChange:判断全选状态

import { defineStore } from "pinia";

interface IGoods {
    name: string,
    price: number,
    num?: number,
    select?: boolean
}
export const userShopStore = defineStore('shop', {
    state() {
        return {
            goods: [
                {
                    name: '羊肉串',
                    price: 20
                },
                {
                    name: '猪肉串',
                    price: 15
                },
                {
                    name: '鸡翅',
                    price: 10
                }
            ] as IGoods[],
            isAllSelect: false
        }
    },
    getters: {
        total(): number {
            return this.goods
                .filter(item => item.select)
                .reduce((total, item) => total += (item.num || 1) * item.price, 0)
        }
    },
    actions: {
        updateNum(index: number, num: number) {
            //初始化num
            this.goods[index].num = this.goods[index].num || 1

            //进行数值操作
            this.goods[index].num! += num
        },
        allSelectChange() {
            //每次点击全选,都需要同步单选状态
            this.goods.forEach((item) => {
                item.select = this.isAllSelect
            })
        },
        singChange() {
            this.isAllSelect = this.goods.every(item => item.select)
        }
    }
})

四、持久化插件

插件介绍

Pinia 插件是一个函数,可以选择返回要添加到 store 的属性。 它需要一个可选参数,一个 context

export function myPiniaPlugin(context) {
  context.pinia // 使用 `createPinia()` 创建的 pinia
  context.app // 使用 `createApp()` 创建的当前应用程序(仅限 Vue 3)
  context.store // 插件正在扩充的 store
  context.options // 定义存储的选项对象传递给`defineStore()`
  // ...
}

持久化实现思路

监听state的变化,把每次变化的结果放到localStorage里面。初始化的时候回显数据

import { PiniaPluginContext } from "pinia";


export function persistedstate(context: PiniaPluginContext) {
  // 初始化回显数据
  const shop = JSON.parse(localStorage.getItem(context.store.$id) || "{}");
  context.store.$patch(shop);


  // 订阅每次state的变化
  context.store.$subscribe(
    (_mutation, state) => {
      localStorage.setItem(_mutation.storeId, JSON.stringify(state));
    },
    {
      detached: true,
    }
  );
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值