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
此处评论已关闭