Pinia 是什么?
引用官方的一句话:Pinia 是一个符合直觉的 Vue.js 状态管理库
是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action
简单说几点它的特性:
- 它支持 Vue3,同时也支持 Vue2,是 Vuex 的完美过渡替代者
- 它极致轻量化,只有
1kb
左右大小 - 它类型安全,对 TypeScript 支持更加友好,支持类型自动推断,
即使在 JavaScript 中亦可为你提供自动补全功能!
(划重点)
Pinia 支持两种写法,跟 Vue3 语法一样,既支持选项式(options)写法,也支持组合式(setup)写法
一、安装 Pinia
在项目中使用 npm 或 yarn 安装 Pinia:
npm install pinia --save
或
yarn add pinia
二、引入和实例化
在 src 下新建 store 文件,在此文件下创建 inde.js 或者 index.ts
// src/store/index.ts
// 引入createPinia方法从pinia
import { createPinia } from 'pinia'
// 实例化 Pinia
const pinia = createPinia()
// 导出
export default pinia
在 main.ts 中引入并使用 pinia
import pinia from '@/store'
app.use(pinia)
三、Pinia 的定义和使用
选项式写法
与 Vue 的选项式 API 类似,我们也可以传入一个带有 state、actions 与 getters 属性的 Option 对象,与 Vue 的选项式 API 类似,我们也可以传入一个带有 state、actions 与 getters 属性的 Option 对象
import { defineStore } from 'pinia'
interface ICount {
count: number
}
export const useCounterStore = defineStore('count', {
state: (): ICount => ({
count: 0,
}),
getters: {
double(): number {
return this.count * 2
},
},
actions: {
increment() {
this.count++
},
},
})
在组件中的使用
<template>
<el-button @click="countAdd">{{ count }}</el-button>
<p>doubleCount: {{ doubleCount }}</p>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/store/modules/count'
const counterStore = useCounterStore()
// vite.config.ts 自动导入 Vue 相关函数
const count = computed(() => counterStore.count)
const doubleCount = computed(() => counterStore.double)
const countAdd = () => {
counterStore.increment()
}
</script>
组合式写法
1、在 Setup Store 中:ref() 就是 state 属性, computed() 就是 getters, function() 就是 actions
2、要让 pinia 正确识别 state,你必须在 setup store 中返回 state 的所有属性。这意味着,你不能在 store 中使用私有属性。不完整返回会影响 SSR ,开发工具和其他插件的正常运行。
3、Setup store 比 Option Store 带来了更多的灵活性,因为你可以在一个 store 内创建侦听器,并自由地使用任何组合式函数。不过,请记住,使用组合式函数会让 SSR 变得更加复杂。
4、Setup store 也可以依赖于全局提供的属性,比如路由。任何应用层面提供的属性都可以在 store 中使用 inject() 访问,就像在组件中一样:
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('count', () => {
const count = ref(0)
const double = computed(() => {
return count.value * 2
})
function increment() {
count.value++
}
return { count, double, increment }
})
在组件中的使用
<template>
<el-button @click="countAdd">{{ count }}</el-button>
<p>doubleCount: {{ double }}</p>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/store/modules/count'
const counterStore = useCounterStore()
// vite.config.ts 自动导入 pinia (storeToRefs) 相关函数
// 为了从 store 中提取属性时保持其响应性,你需要使用 storeToRefs()。它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。请注意,你可以直接从 store 中解构 action,因为它们也被绑定到 store 上
const { count, double } = storeToRefs(counterStore)
const countAdd = () => {
counterStore.increment()
}
</script>
四、pinia 持久化存储
1、安装持久化插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
或
yarn add pinia-plugin-persistedstate
2、将插件添加到 pinia 实例上
import { createPinia } from 'pinia' //引入pinia
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' //引入持久化插件
const pinia = createPinia() //创建pinia实例
pinia.use(piniaPluginPersistedstate) //将插件添加到 pinia 实例上
export default pinia //导出pinia用于main.js注册
3、默认持久化的配置项
- 使用 localStorage 进行存储
- store.$id 作为 storage 默认的 key
- 使用 JSON.stringify / JSON.parse 进行序列化/反序列化
- 整个 state 默认将被持久化
4、高级使用:自行配置持久化配置项
key:存储名称。
storage:存储方式。
path:用于指定 state 中哪些数据需要被持久化。[] 表示不持久化任何状态,undefined 或 null 表示持久化整个 state。
import { defineStore } from "pinia"
const useUserInfoStore = defineStore('userInfo', {
// defineStore('userInfo',{}) userInfo就是这个仓库的名称name
state: () => ({
username:'张三',
age: 18,
like: '睡觉',
obj:{ money:10000,friend:66 }
}),
getters: {
...........
},
action:{
.........
},
persist: {
key: 'piniaStore', //存储名称
storage: sessionStorage, // 存储方式
paths: ['username', 'like','obj'], //指定 state 中哪些数据需要被持久化。[] 表示不持久化任何状态,undefined 或 null 表示持久化整个 state
},
})
export default useUserInfoStore