unipp === 状态管理 Pinia 使用
目录
介绍
Pinia 是什么?
项目结构
基本示例
pinia-plugin-persistedstate
安装
用法
配置
key
serializer
storage
pick
omit
全局持久性选项
介绍
uni-app 内置了 Pinia 。Vue 2 项目暂不支持
注意事项
-
使用
HBuilder X
HBuilder X 已内置了 Pinia,无需手动安装,按照下方示例使用即可。
App 升级时,如果之前使用
HBuilder X 版本 < 4.14
打包,现在使用HBuilder X 版本 >= 4.14
,更新时需要整包更新不可使用wgt更新(在4.14
时升级了vue
版本,低版本的基座和高版本 wgt 资源包会导致使用 Pinia 时报错) -
使用
CLI
4.14 之前
:执行yarn add pinia@2.0.36
或npm install pinia@2.0.36
安装,要固定版本4.14 之后
:执行yarn add pinia
或npm install pinia
安装,可不指定版本
Pinia 是什么?
Pinia(发音为 /piːnjʌ/
,如英语中的 peenya
) 是 Vue 的存储库,它允许您跨组件、页面共享状态。在服务器端以及小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:
- Devtools 支持
- 追踪 actions、mutations 的时间线
- 在组件中展示它们所用到的 Store
- 让调试更容易的 Time travel
- 热模块更换
- 不必重载页面即可修改 Store
- 开发时可保持当前的 State
- 为 JS 开发者提供适当的 TypeScript 支持以及 自动补全 功能。
#
项目结构
├── pages
├── static
└── stores└── counter.js
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
基本示例
在 main.js
中编写以下代码:
import App from './App'
import { createSSRApp } from 'vue';
import * as Pinia from 'pinia';export function createApp() {const app = createSSRApp(App);app.use(Pinia.createPinia());return {app,Pinia, // 此处必须将 Pinia 返回};
}
首先创建一个 Store:
// stores/counter.js
import { defineStore } from 'pinia';export const useCounterStore = defineStore('counter', {state: () => {return { count: 0 };},// 也可以这样定义// state: () => ({ count: 0 })actions: {increment() {this.count++;},},
});
然后在组件中使用它:
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
counter.count++
// 自动补全! ✨
counter.$patch({ count: counter.count + 1 })
// 或使用 action 代替
counter.increment()
</script>
<template><!-- 直接从 store 中访问 state --><div>Current Count: {{ counter.count }}</div>
</template>
为实现更多高级用法,你甚至可以使用一个函数 (与组件 setup()
类似) 来定义一个 Store:
export const useCounterStore = defineStore('counter', () => {const count = ref(0);function increment() {count.value++;}return { count, increment };
});
复制代码
如果你还不熟悉 setup() 函数和组合式 API,Pinia 也提供了一组类似 Vuex 的 映射 state 的辅助函数。
你可以用和之前一样的方式来定义 Store,然后通过 mapStores()、mapState() 或 mapActions() 访问:
const useCounterStore = defineStore('counter', {state: () => ({ count: 0 }),getters: {double: (state) => state.count * 2,},actions: {increment() {this.count++},},
})const useUserStore = defineStore('user', {// ...
})// 使用
import { mapState, mapStores, mapActions } from 'pinia'
export default defineComponent({computed: {// 其他计算属性// ...// 允许访问 this.counterStore 和 this.userStore...mapStores(useCounterStore, useUserStore)// 允许读取 this.count 和 this.double...mapState(useCounterStore, ['count', 'double']),},methods: {// 允许读取 this.increment()...mapActions(useCounterStore, ['increment']),},
})
pinia-plugin-persistedstate
此插件与 pinia>=2.0.0
兼容, 请确保在继续之前 已安装 Pinia 。 pinia-plugin-persistedstate
具有许多功能,使 Pinia store 的持久化变得轻松且可配置:
- 一个类似于 vuex-persistedstate的 API。
- Per-store 配置.
- 自定义存储和自定义数据序列化程序。
- Pre/post persistence/hydration hooks.
- 每个store有多个配置。
安装
- 用您喜欢的软件包管理器安装依赖项:
pnpm add pinia-plugin-persistedstate
- 将插件添加到你的 pinia 实例中:
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
用法
创建 Store 时,将 persist
选项设置为 true
。
使用选项式 Store 语法:
import { defineStore } from 'pinia'export const useStore = defineStore('main', {state: () => {return {someState: '你好 pinia',}},persist: true,
})
或者使用组合式 Store 语法:
import { defineStore } from 'pinia'export const useStore = defineStore('main',() => {const someState = ref('你好 pinia')return { someState }},{persist: true,}
)
现在,你的整个 Store 将使用默认持久化配置
保存。
配置
该插件的默认配置如下:
- 使用 localStorage 进行存储
- store.$id 作为 storage 默认的 key
- 使用 JSON.stringify/JSON.parse 进行序列化/反序列化
- 整个 state 默认将被持久化
如何你不想使用默认的配置,那么你可以将一个对象传递给 Store 的 persist
属性来配置持久化。
import { defineStore } from 'pinia'export const useStore = defineStore('main', {state: () => ({someState: '你好 pinia',}),persist: {// 在这里进行自定义配置},
})
key
- 类型:
string
- 默认值:
store.$id
用于引用存储中存储的反序列化数据的 Key。
import { defineStore } from 'pinia'export const useStore = defineStore('store', {state: () => ({someState: 'hello pinia',}),persist: {key: 'my-custom-key',},
})
此存储将在localStorage
中的my-custom-key
项下持久化。
serializer
- 类型: Serializer
- 默认值: JSON.stringify/destr
自定义序列化程序,用于在持久化之前序列化数据,并在解除冻结存储之前反序列化数据。 必须有 serialize: (value: StateTree) => string
和 deserialize: (value: string) => StateTree
方法。
import { defineStore } from 'pinia'
import { parse, stringify } from 'zipson'export const useStore = defineStore('store', {state: () => ({someState: 'hello pinia',}),persist: {serializer: {deserialize: parse,serialize: stringify}},
})
此存储将使用 zipson的
stringify
/parse
来处理序列化/反序列化,并添加了压缩。
storage
- 类型: StorageLike
- 默认值: localStorage
将数据保存到 Storage 中。 必须有 getItem: (key: string) => string | null
和 setItem: (key: string, value: string) => void
方法。
import { defineStore } from 'pinia'export const useStore = defineStore('store', {state: () => ({someState: 'hello pinia',}),persist: {storage: sessionStorage,},
})
此存储将保留在 sessionStorage中。
存储必须是同步的。
pick
- 类型:
string[] | Path<StateTree>[]
- 默认值:
undefined
用于选择应持久化的内容的点表示法路径数组 []
表示不持久化任何状态, undefined
表示持久化整个状态。
import { defineStore } from 'pinia'export const useStore = defineStore('store', {state: () => ({save: {me: 'saved',notMe: 'not-saved',},saveMeToo: 'saved',}),persist: {pick: ['save.me', 'saveMeToo'],},
})
在此存储中,将保留
save.me
和saveMeToo
。save.notMe
不会持久化。
omit
- 类型:
string[] | Path<StateTree>[]
- 默认值:
undefined
要从应持久化的内容中省略的点表示法路径数组。 []
或 undefined
表示整个状态持续存在(不遗漏任何内容)。
import { defineStore } from 'pinia'export const useStore = defineStore('store', {state: () => ({ignore: {me: 'not-saved',notMe: 'saved',},ignoreMeToo: 'not-saved',}),persist: {omit: ['ignore.me', 'ignoreMeToo'],},
})
在这个存储中,只有
ignore.notMe
值将被持久化。ignore.me
和ignoreMeToo
不会被保留
全局持久性选项
安装插件时,您可以使用公开的 createPersistedState
方法来初始化带有全局选项的插件,而不是使用默认导出。这些选项成为应用程序中所有商店的新默认选项。
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'const pinia = createPinia()pinia.use(createPersistedState({storage: sessionStorage,
}))
在此示例中,每个声明 persist: true
的存储将默认地将数据保存到 sessionStorage
中。
可用的全局选项包括:
- storage
- serializer
- debug
传递给存储的 persist
配置的任何选项都将覆盖在全局选项中声明的对应选项。