Store

每个模块都是独立的,互不影响,这样就不用跟vuex一样,还要分模块

定义数据

import {
defineStore } from 'pinia' // 导入 pinia 中的功能模块 // 创建容器 // 参数一:容器名 // 参数二:容器的内容 const useMainStore = defineStore('main', {
// pinia 状态管理的数据,通过箭头函数返回一个对象 // 相当于 vue 中的 data 数据 state: () => {
return {
count: 1, } }, }) // 导出容器 export {
useMainStore }

使用数据

  • 可以直接使用,数据是响应式的
  • 但是不能结构,结构出来的话,会丢失数据的响应式
<template>
  <!-- 后面相同的调用,都是基于第一次计算的值 -->
  <p>{
{
mainStore.count}}</p> </template> <script setup lang="ts"> // 导入 pinia 实例 import {
useMainStore } from './stores/user' // 实例化容器 const mainStore = useMainStore() </script>

Getters

类似于vue中的计算属性,会根据数据依赖项改变而重新计算,也是会被缓存的

定义Getters

import {
defineStore } from 'pinia' // 导入 pinia 中的功能模块 // 创建容器 // 参数一:容器名 // 参数二:容器的内容 const useMainStore = defineStore('main', {
// pinia 状态管理的数据,通过箭头函数返回一个对象 // 相当于 vue 中的 data 数据 state: () => {
return {
count: 10, } }, // 相当于 vue 中的 computed 计算属性 getters: {
// 普通定义,不带参数的 comp(state): number {
return this.count++ }, // 计算属性调用其他计算属性 comp1(): number {
return this.comp * 2 }, // 带参数的 comp2() {
return (payload: number): number => {
return this.count + payload } }, }, }) // 导出容器 export {
useMainStore }

使用Getters

<template>
  <!-- 后面相同的调用,都是基于第一次计算的值 -->
  <p>{
{
mainStore.comp }}</p> <br /> <p>{
{
mainStore.comp1 }}</p> <br /> <p>{
{
mainStore.comp2(10) }}</p> </template> <script setup lang="ts"> // 导入 pinia 实例 import {
useMainStore } from './stores/user' // 实例化容器 const mainStore = useMainStore() </script>

action

方法都写在里面,不管同步还是异步

定义action

import {
defineStore } from 'pinia' // 导入 pinia 中的功能模块 import axios from 'axios' // 创建容器 // 参数一:容器名 // 参数二:容器的内容 const useMainStore = defineStore('main', {
// pinia 状态管理的数据,通过箭头函数返回一个对象 // 相当于 vue 中的 data 数据 state: () => {
return {
count: 10, list: [], } }, // 相当于 vue 中的 computed 计算属性 getters: {
// 普通定义,不带参数的 comp(state): number {
return this.count++ }, // 计算属性调用其他计算属性 comp1(): number {
return this.comp * 2 }, // 带参数的 comp2() {
return (payload: number): number => {
return this.count + payload } }, }, // 相当于 vue 中的 methods 方法 actions: {
// 不带参数的 addCount() {
this.count++ }, // 带参数的 addCount1(num: number): void {
this.count += num }, // 异步方法 async getData() {
let {
data } = await axios.get('https://cnodejs.org/api/v1/topics') if (data.success) this.list = data.data }, }, }) // 导出容器 export {
useMainStore }

使用action

<template>
  <!-- 后面相同的调用,都是基于第一次计算的值 -->
  <p>{
{
mainStore.comp }}</p> <br /> <p>{
{
mainStore.comp1 }}</p> <br /> <p>{
{
mainStore.comp2(10) }}</p> <br /> <button @click="mainStore.addCount">改变count</button> <br /> <button @click="mainStore.addCount1(6)">传入参数,根据参数改变值</button> <br /> <button @click="mainStore.getData">点击获取数据</button> <ul> <li v-for="item in mainStore.list" :key="item.id">{
{
item.title }}</li> </ul> </template> <script setup lang="ts"> // 导入 pinia 实例 import {
useMainStore } from './stores/user' // 实例化容器 const mainStore = useMainStore() </script>

购物车案例

user.ts

import {
defineStore } from 'pinia' // 导入 pinia 中的功能模块 const useMainStore = defineStore('main', {
state: () => {
return {
// 商品数组 goodsList: [ {
id: 0, checked: true, // 选中状态 goodsTitle: '羊肉串', // 商品名 goodsPrice: 10, // 商品单价 goodsCount: 1, // 商品数量 computedPrice: 10, // 商品小计 }, {
id: 1, checked: false, goodsTitle: '鸡翅', goodsPrice: 15, goodsCount: 1, computedPrice: 15, }, {
id: 2, checked: false, goodsTitle: '牛肉串', goodsPrice: 20, goodsCount: 1, computedPrice: 20, }, ], // 总计 priceAll: 0, // 全选复选框的选中状态 allChecked: false, } }, getters: {
// +1 addOne() {
return (index: number) => ++this.goodsList[index].goodsCount }, // -1 reduceOne() {
return (index: number) => {
if (this.goodsList[index].goodsCount <= 0) return return --this.goodsList[index].goodsCount } }, // 计算总价 computedAllPrice() {
// 过滤一下,只对选中的计算总价 const newList = this.goodsList.filter((item) => item.checked) let moneys = 0 newList.forEach((item) => {
moneys += item.computedPrice }) return moneys }, }, actions: {
// 计算小计 computedPrice(index: number) {
let moneys = this.goodsList[index].goodsPrice * this.goodsList[index].goodsCount this.goodsList[index].computedPrice = moneys }, // 点击全选,改变每一项的选中状态 changeItemChecked(checked: boolean) {
this.allChecked = checked this.goodsList.forEach((item) => (item.checked = checked)) }, // 点击子项,改变子项状态。子项有一项没选中,全选就不选中 itemChange(status: boolean, index: number) {
this.goodsList[index].checked = status // 遍历商品数组,只要有一项的选中状态为false,则全选就不选中 let flag = this.goodsList.some((item) => !item.checked) this.allChecked = flag ? false : true }, }, }) // 导出容器 export {
useMainStore }

App.vue

<template>
  <div>
    <span>全选</span
    ><input
      type="checkbox"
      @click="allChecked"
      :checked="mainStore.allChecked"
    />
  </div>
  <div v-for="(item, index) in mainStore.goodsList" :key="item.id" class="box">
    <input
      type="checkbox"
      :checked="item.checked"
      @click="itemCheckedChange($event, index)"
    />
    <span>商品名:{
{
item.goodsTitle }}---</span> <span>商品价格:{
{
item.goodsPrice }}---</span> <button @click="add(index)">+</button> <span>{
{
item.goodsCount }}</span> <button @click="reduce(index)">-</button> <span>---小计:{
{
item.computedPrice }}</span> </div> <div> <span>总价:{
{
mainStore.computedAllPrice }}</span> </div> </template> <script setup lang="ts"> // 导入 pinia 实例 import {
useMainStore } from './stores/user' // 实例化容器 const mainStore = useMainStore() // 点击+1 const add = (index: number) => {
mainStore.addOne(index) mainStore.computedPrice(index) } // 点击-1 const reduce = (index: number) => {
mainStore.reduceOne(index) mainStore.computedPrice(index) } // 点击全选 const allChecked = (e: any) => {
mainStore.changeItemChecked(e.target.checked) } // 点击子项的复选框 const itemCheckedChange = (e: any, index: number) => {
mainStore.itemChange(e.target.checked, index) } </script>

如图所示,购物车基本的功能都有
在这里插入图片描述
闲着没事,又写了一版,采用的vant+vue3+ts,主要代码如下
main.ts

import {
createApp } from 'vue' import {
createPinia } from 'pinia' import {
NavBar, Checkbox, Button, Space, ActionBar, ActionBarButton, } from 'vant' import App from './App.vue' import router from './router' import './assets/main.css' import 'vant/lib/index.css' // 引入vant样式 const app = createApp(App) app.use(createPinia()) app.use(router) app.use(NavBar) app.use(Checkbox) app.use(Button) app.use(Space) app.use(ActionBar) app.use(ActionBarButton) app.mount('#app')

App.vue

<template>
  <van-nav-bar title="购物车" />
  <div
    v-for="(item, index) in mainStore.goodsList"
    :key="item.id"
    class="goodsCard"
  >
    <div class="item">
      <van-checkbox
        v-model="item.checked"
        @change="itemStatusChange($event, index)"
      />
      <div class="left">图片</div>
      <div class="right">
        <div class="title">{
{
item.goodsTitle }}</div> <div class="price">{
{
item.goodsPrice }}</div> <div class="littleMoney"> <span>小计:{
{
item.computedPrice }}</span> <span class="count"> <van-space> <van-button plain type="primary" size="small" @click="addOne(index)" > + </van-button> {
{
item.goodsCount }} <van-button plain type="primary" size="small" @click="reduceOne(index)" > - </van-button> </van-space> </span> </div> </div> </div> </div> <van-action-bar> <van-space> <!-- <van-checkbox v-model="mainStore.allChecked" @change="allCheck" >全选</van-checkbox > --> <input type="checkbox" :checked="mainStore.allChecked" @change="allCheck" />全选 <span>总计:¥{
{
mainStore.priceAll }}</span> </van-space> <van-action-bar-button type="danger" text="立即购买" /> </van-action-bar> </template> <script setup lang="ts"> // 导入 pinia 实例 import {
useMainStore } from './stores/goods' // 实例化容器 const mainStore = useMainStore() // 计算总计 mainStore.getPriceAll() // 点击+1 const addOne = (index: number) => {
mainStore.addOne(index) } // 点击-1 const reduceOne = (index: number) => {
mainStore.reduceOne(index) } // 点击单选 const itemStatusChange = (checked: boolean, index: number) => {
mainStore.itemStatusChange(checked, index) } // 点击全选 const allCheck = (e: any) => {
mainStore.allCheck(e.target.checked) } </script> <style scoped> .goodsCard {
margin-bottom: 10px; border-radius: 20px; overflow: hidden; } .item {
display: flex; padding: 10px; background-color: #f7f8fa; } .item .left {
width: 100px; height: 100px; background-color: pink; border-radius: 10px; margin: 0 10px; } .item .right {
flex: 1; display: flex; flex-direction: column; justify-content: space-between; } .item .right .littleMoney {
display: flex; justify-content: space-between; align-items: center; } .item .right .littleMoney .count {
display: flex; align-items: center; } </style>

goods.ts(数据存放的地方)

import {
defineStore } from 'pinia' // 导入 pinia 中的功能模块 const useMainStore = defineStore('main', {
state: () => {
return {
// 商品数组 goodsList: [ {
id: 0, checked: true, // 选中状态 goodsTitle: '玫瑰花', // 商品名 goodsPrice: 10, // 商品单价 goodsCount: 1, // 商品数量 computedPrice: 10, // 商品小计 }, {
id: 1, checked: false, goodsTitle: '月季花', goodsPrice: 15, goodsCount: 1, computedPrice: 15, }, {
id: 2, checked: false, goodsTitle: '紫罗兰', goodsPrice: 20, goodsCount: 1, computedPrice: 20, }, ], // 总计 priceAll: 0, // 全选复选框的选中状态 allChecked: false, } }, getters: {
// +1 addOne() {
return (index: number) => {
// 让这一项的数量+1 ++this.goodsList[index].goodsCount // 并计算小计 小计=数量*价格 this.goodsList[index].computedPrice = this.goodsList[index].goodsCount * this.goodsList[index].goodsPrice // 计算总计 this.getPriceAll() } }, // -1 reduceOne() {
return (index: number) => {
// 最小只能为0 if (this.goodsList[index].goodsCount <= 0) return // 让这一项的数量-1 --this.goodsList[index].goodsCount // 并计算小计 小计=数量*价格 this.goodsList[index].computedPrice = this.goodsList[index].goodsCount * this.goodsList[index].goodsPrice // 计算总计 this.getPriceAll() } }, // 点击单选,改变这一项的选中状态 itemStatusChange() {
return (checked: boolean, index: number) => {
// 首先把这一项的选中状态改变 this.goodsList[index].checked = checked // 然后再判断是否需要勾选全选(遍历商品数组,如果checked都为true,则勾选,反之不勾选) let flag = this.goodsList.every((item) => item.checked) this.allChecked = flag ? true : false // 计算总计 this.getPriceAll() } }, // 点击全选,上面的每一项都跟全选的状态一样 allCheck() {
return (checked: boolean) => {
// 首先改变全选状态 this.allChecked = checked // 然后改变上面的每一项的选中状态 this.goodsList.forEach((item) => (item.checked = checked)) // 计算总计 this.getPriceAll() } }, // 计算总计的方法 getPriceAll() {
return () => {
// 计算总计 只有选中的才计算 let newList = this.goodsList.filter((item) => item.checked) this.priceAll = newList.reduce((sum, item) => {
return (sum += item.goodsPrice * item.goodsCount) }, 0) } }, }, actions: {
}, }) // 导出容器 export {
useMainStore }

界面如下
在这里插入图片描述

原文链接:https://blog.csdn.net/qq_52845451/article/details/128995010

最后修改:2023 年 10 月 30 日
如果觉得我的文章对你有用,请随意赞赏