Pinia 状态管理
什么是 Pinia ?
Pinia最初是在 2019 年 11 月左右重新设计使用 Composition API的 Vue Store 外观的实验。从那时起,最初的原则仍然相同,但 Pinia 适用于 Vue 2 和 Vue 3 ,并且不需要你使用组合 API。除了安装和 SSR 之外,两者的 API 都是相同的,并且这些文档针对 Vue 3 ,并在必要时提供有关 Vue 2 的注释,以便 Vue 2 和 Vue 3 用户可以阅读!
为什么要使用 Pinia?
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。ç 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,则会将您的应用程序暴露给安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:
安装 Pinia
yarn add pinia
# or with npm
npm install pinia
复制代码
Pinia 入门
store
可以通过 defineStore()
来定义 store
来存在管理状态,并且它需要一个唯一的名称,作为第一个参数传递:
import { defineStore } from 'pinia'
export const useStore = defineStore('main', {
// other options...
})
复制代码
使用 store
在组件内导入需要的 store
,
注意⚠️:
store`是一个用 包裹的对象`reactive`,这意味着不需要`.value`在 getter 之后编写,但是像`props`in一样`setup
state
定义 state
import { defineStore } from 'pinia'
export const useCounterStore = defineStore({
id: 'haijun',
state: () => ({
// 定义状态属性
str: "前端自学社区"
}),
})
复制代码
访问 state
通过store
实例来访问
<script setup lang="ts">
import {useCounterStore} from '../stores/counter';
const store = useCounterStore()
onMounted(()=> {
console.log(store.counter) //访问 state
console.log(store.resultCode)
})
</script>
复制代码
重制 state
可以通过调用 store 上的方法将状态重置为其初始值:$reset()
const store = useCounterStore()
store.$reset()
复制代码
改变 state
有两种方法
直接修改 state
const store = useCounterStore()
store.code++
复制代码
通过 patch
来修改,一次可修改多个 state
const store = useCounterStore()
store.$patch((state) => {
state.code = 404
state.counter++
state.carList.push({id:3,name:'奥迪🇦🇹'})
})
复制代码
添加新的 state
有两种方法
通过 store 的 $state
来赋值一个对象,对象中可以添加多个state
store.$state = {title: '更换后的store' , author: '海军'}
复制代码
通过pinia
实例来改变 state
, 这在SSR 中使用。
订阅状态
观察状态和变化$subscribe()
<hr/>
Getter
Pinia
中的 getter
与 Vuex
中的getter
效果是一样的,接受一个 state
参数,用来访问store
的状态,具有缓存作用
。
import { defineStore } from 'pinia'
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
counter: 0,
code: 200,
carList:[
{
id:1,
name: '特斯拉'
},
{
id:2,
name: '奔驰'
}
]
}),
getters: {
doubleCount: (state) => state.counter * 2,
resultCode: (state) => state.code + 4,
otherGetter(){
return this.resultCode * 4
},
filterIdCarList: (state) => {
return (id:number) => state.carList.filter(i => i.id == id)
}
},
})
复制代码
组件中访问 getter
直接通过store
实例上访问 getter
:
<template>
<p>Double count is {{ store.doubleCount }}</p>
</template>
<script setup lang="ts">
import {useCounterStore} from '../stores/counter';
const store = useCounterStore()
</script>
复制代码
访问其它 Getter
可以在一个 getter 中访问其它的 getter 与 computer
类似。 它可以组合多个 getter
, 可以通过 this
来访问多个 getter
getters: {
doubleCount: (state) => state.counter * 2,
resultCode: (state) => state.code + 4,
// 组合 多个 getter 返回处理结果
otherGetter(){
return this.resultCode * 4 + this.doubleCount * 4
},
},
复制代码
参数传递 Getter
getter
本身是用来计算的,本身不可能将参数传递给给它的。但可以通过返回一个函数来接受参数,进行状态处理。
getters: {
//第一层传递参数 state, 以便在函数中处理
filterIdCarList: (state) => {
//第二层: 返回一个函数,用来接收传递的参数,进行数据处理
return (id:number) => state.carList.filter(i => i.id == id)
}
}
复制代码
组件中使用
<h2>{{filterData(1)}}</h2>
<!-- [ { "id": 1, "name": "特斯拉" } ] 返回处理的结果-->
<script setup lang="ts">
import {useCounterStore} from '../stores/counter';
const store = useCounterStore()
const filterData = store.filterIdCarList
</script>
复制代码
⚠️⚠️⚠️
通过返回函数后,它不具有缓冲的效果了,它只是调用了该函数。不过可以在 getter 内部做缓存结果。 【不常用】
import { defineStore } from 'pinia'
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
carList:[
{
id:1,
name: '特斯拉',
sell: false
},
{
id:2,
name: '奔驰',
sell: true,
price: 25
},
{
id: 1,
name: '奥迪Q5',
sell: true,
price: 67
}
]
}),
getters: {
getSellCarList: (state) => {
//用个变量存储起来
const filterIdCar = state.carList.filter(i => i.sell)
return (price: number) => filterIdCar.filter(k => k.price == price)
}
}
})
复制代码
访问其它 store 中的 getter
还可以访问其它 stroe 中的 getter,
导入其它store
import { useOtherStore } from './other-store'
getters: {
otherGetter(state) {
const otherStore = useOtherStore
//访问其它store 中的state
return state.localData + otherStore.data
},
},
复制代码
action
它 与 Vuex
中的 Action 是一样的效果,使用也一样。 它可以访问整个store
实例,它是异步的
export const useUsers = defineStore('users', {
state: () => ({
userData: null,
// ...
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`Welcome back ${this.userData.name}!`)
} catch (error) {
return error
}
},
},
})
复制代码
在组件使用 action
,它和 getter
使用一样
<script setup lang="ts">
import { useUsers } from '../stores/user';
const store = useUsers()
const filterData = store.registerUser('admin','123456')
</script>
复制代码
访问其它 store 实例
//user.js
import { defineStore } from 'pinia'
export const useMember = defineStore({
id: 'member',
state: () => ({
memberList: [
{
id: 111,
name: '张飞'
},
{
id: 222,
name: '小红'
}
]
}),
getters: {
addMember: (state) => {
return (obj:any) => {
state.memberList.push(obj)
}
}
},
actions: {
}
})
复制代码
import { defineStore } from 'pinia'
import {useMember} from './user'
// 导入axios
import axios from 'axios'
export const useCounterStore = defineStore({
id: 'counter',
state: () => ({
}),
actions: {
async getMenuData(){
const useMembers = useMember()
const resultData = await axios.get('http://localhost:3000/menu')
//访问其它 store 的 getter state action
useMembers.addMember({id:333,name: '老张'})
console.log(useMembers.memberList)
}
}
})
复制代码
最后
欢迎一起交流学习,关注公众公众号:前端自学社区
评论