1.什么是 Pinia
Pinia 是 vue 官方成员在2019年11月重新设计的一个状态存储库,它允许你跨组件/页面共享状态,并且是响应式的,类似于 vuex。现在 vuex 已经更新到4.x版本了,你可以认为 pinia 是作为 vuex@5.x 的一种存在。
与vuex对比:
没有 mutations,只有 actions。
没有命名空间模块,pinia的store是扁平化结构,你创建的多个store都是相互隔离的,没有嵌套关系。
不再需要注入、导入函数。
2.引入 pinia
引用
npm install pinia
创建
// src/stores/index.js
import { createPinia } from "pinia";
const pinia = createPinia()
export default pinia
//main.js
import pinia from './stores'
app.use(pinia)
3.定义一个store
通过 defineStore 来定义 store,它需要一个唯一的名称,作为第一个参数传入
只有3个模块:state,getters,actions
// @/store/firstStore.js
import { defineStore } from 'pinia'
// 定义并导出容器,第一个参数是容器id(myStore),必须唯一,用来将所有的容器
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
4.state
定义state
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
使用state
注意,将 store 解构之后,就不是响应式的了,如果想要解构,则需要使用 storeToRefs 函数包裹。
原因很简单,store 其实就是一个 reactive 对象,当我们解构的时候,就不是响应式数据了,就像 vue3 中一样,需要使用 toRefs 函数。
import { useFirstStore } from '@/store/firstStore.js'
import { storeToRefs } from 'pinia
<template>
{{ '直接使用' + firstStore.count}}
{{count}}
{{'解构使用' + arr}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
console.log(firstStore.count) //直接使用 0
// 这样就不是响应式的了,当我们修改count的值的时候,页面不会响应式变化
const { count,arr } = firstStore // 错误的做法
const { count,arr } = storeToRefs(firstStore) // 正确的做法
</script>
修改state
pinia可以直接修改state中值,不同vuex必须使用mutations修改值
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{count}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
// 方式一,直接修改
firstStore.count += 1
// 方式二,如果修改多个数据,可以使用$patch批量修改
firstStore.$patch({
count:firstStore.count + 1,
arr:[...firstStore.arr,4]
})
// 方式三: $patch一个函数
firstStore.$patch(state=>{
state.count++
state.arr.push(4)
})
// 方式四,调用actions
firstStore.changeCount()
// 方式五,替换整个state
firstStore.$state={
count:2,
arr:[1,2,3,4]
}
// 方式六:重置state
firstStore.$reset()
</script>
5.Getters
定义 getters
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{
// 依赖state
doubleCount(state){
return state.count *2
},
// 依赖其他的getters, :number 是指定返回值类型为number类型
otherCount():number{
return this.doubleCount + 1
}
},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{}
})
使用getters
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{firstStore.doubleCount}}
{{firstStore.otherCount}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
console.log(firstStore.doubleCount)
console.log(firstStore.otherCount)
</script>
6.Actions
定义 actions,actions可以写异步请求,然后在修改state中值
import { defineStore } from 'pinia'
// 挂载到根容器上
export const useFirstStore = defineStore('myStore',{
// 定义state,用来存储状态的
state:()=>{
return {
count:0,
arr:[1,2,3]
}
},
// 定义getters,类似于computed,具有缓存g功能
getters:{
// 依赖state
doubleCount(state){
return state.count *2
},
// 依赖其他的getters, :number 是指定返回值类型为number类型
otherCount():number{
return this.doubleCount + 1
}
},
// 定义actions,类似于methods,用来修改state,做一些业务逻辑
actions:{
// 接收一个参数num,参数的类型是number类型
addCount(num:number){
// 通过this获取state中的数据,就像vue2的optionsApi一样
this.count+=num
}
}
})
调用 actions
import { useFirstStore } from '@/store/firstStore.js'
<template>
{{firstStore.count}}
</template>
<script setup lang='ts'>
// 拿到store
const firstStore = useFirstStore()
firstStore.addCount(10)
</script>