Pinia 状态管理
本篇将介绍 Pinia 全局状态管理(Options API 和 Setup Store 两种形式 )及两种数据持久化方法(pinia-plugin-unistorage 和 pinia-plugin-persistedstate) 其中 pinia-plugin-unistorage 是基于 pinia-plugin-persistedstate 封装的 uni-app 持久化插件。
提示
snail-uni 默认集成 pinia-plugin-unistorage 数据持久化,本篇会介绍pinia-plugin-persistedstate 的使用,根据个人喜好进行修改。
store 目录
├── store # 状态根目录
│ │── modules # 模块
│ │ │── counter.ts # counter 模块
│ │ │── user.ts # user 模块
│ │── index.ts # 导出所有模块其中 store/modules/counter.ts 为 Setup Store 模式示例,store/modules/user.ts 为 Options API 模式示例。
选项式 API
选项式API示例代码如下 :
// store/modules/user.ts
import { defineStore } from 'pinia';
import { IUserInfo } from '@/types/user';
const initUserState = {
nickName: '',
avatarUrl: '',
userId: '',
gender: 0,
};
export const useUserStore = defineStore('user', {
state: () => {
return {
userInfo: { ...initUserState } as IUserInfo,
Authorization: 'SNAIL_UNI00000001',
};
},
getters: {
nickName: (state) => state.userInfo.nickName,
},
actions: {
/** 设置用户信息 */
setUserInfo(data: IUserInfo) {
this.userInfo = data;
},
/** 设置请求token */
setToken(token: string) {
this.Authorization = token;
},
}
});// store/modules/user.js
import { defineStore } from 'pinia';
const initUserState = {
nickName: '',
avatarUrl: '',
userId: '',
gender: 0,
};
export const useUserStore = defineStore('user', {
state: () => {
return {
userInfo: { ...initUserState },
Authorization: 'SNAIL_UNI00000001',
};
},
getters: {
nickName: (state) => state.userInfo.nickName,
},
actions: {
/** 设置用户信息 */
setUserInfo(data) {
this.userInfo = data;
},
/** 设置请求token */
setToken(token) {
this.Authorization = token;
},
}
});useUserStore状态管理名称,建议命名规则:use+名称+Store- defineStore(
'user', {}) 其中user是Store 的唯一 ID state定义状态变量, 推荐使用箭头函数:
export const useUserStore = defineStore('user', {
state: () => ({
firstName: 'snail',
lastName: 'uni',
})
})getter完全等同于store的state的计算值。可以通过defineStore()中的getters属性来定义它们。推荐使用箭头函数,并且它将接收state作为第一个参数:
export const useUserStore = defineStore('user', {
state: () => ({
firstName: 'snail',
lastName: 'uni',
}),
getters: {
fullName: (state) => state.firstName + state.lastName,
},
})action定义方法,处理一些业务逻辑:
export const useUserStore = defineStore('user', {
actions: {
/** 设置用户信息 */
setUserInfo(data: IUserInfo) {
this.userInfo = data;
},
}
})组合式 API
与 Vue 组合式 API 的 setup 函数 相似,我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。
import { defineStore } from 'pinia';
// snail-uni 自动导入可以不用引入
import { ref } from 'vue';
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
}
);import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
}
);在 Setup Store 中:
ref()就是state属性computed()就是gettersfunction()就是actions
注意,要让 pinia 正确识别 state,你必须在 setup store 中返回 state 的所有属性
说明
pinia 语法糖选择和在 Vue 中如何选择组合式 API 与选项式 API 一样,选择你觉得最舒服的那一个就好。两种语法都有各自的优势和劣势。Option Store 更容易使用,而 Setup Store 更灵活和强大。详情查看pinia文档
持久化存储插件
snail-uni 默认集成了 pinia-plugin-unistorage 持久化存储插件,该插件是 pinia-plugin-persistedstate 的 uniapp 版本。
配置
pinia-plugin-unistorage 配置示例:
// src/main.ts
import { createSSRApp } from 'vue';
import App from './App.vue';
import * as Pinia from 'pinia';
// @docs https://github.com/dishait/pinia-plugin-unistorage?tab=readme-ov-file#readme
import { createUnistorage } from 'pinia-plugin-unistorage';
export function createApp() {
const app = createSSRApp(App);
const store = Pinia.createPinia();
store.use(createUnistorage());
app.use(store);
return {
app,
Pinia,
};
}注: 必须返回 Pinia, 否则不生效
使用示例
import { defineStore } from 'pinia';
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
},
{
unistorage: true,
},
);iimport { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
}
},
unistorage: true,
})使用说明:
unistorage属性为true时,缓存state所有数据, 默认为false- 缓存指定
state参数
unistorage: {
key: "counter",
paths: ["count"],
},key缓存的键,默认为该store的id,这里是counter, 一般不需要修改,除非有特殊需求。paths需要缓存的路径,这里设置count会被缓存- 钩子
unistorage: {
// 初始化恢复前触发
beforeRestore(ctx) {},
// 初始化恢复后触发
afterRestore(ctx) {},
},- 序列化
unistorage: {
serializer: {
// 序列化,默认为 JSON.stringify
serialize(v) {
return JSON.stringify(v);
},
// 反序列化,默认为 JSON.parse
deserialize(v) {
return JSON.parse(v);
},
},
},替换默认
在替换之前,需要先卸载默认插件:
npm uninstall pinia-plugin-unistoragepnpm remove pinia-plugin-unistorageyarn remove pinia-plugin-unistorage再移除 pinia-plugin-unistorage 配置代码:
// src/main.ts
import { createSSRApp } from 'vue';
import App from './App.vue';
import * as Pinia from 'pinia';
// @docs https://github.com/dishait/pinia-plugin-unistorage?tab=readme-ov-file#readme
import { createUnistorage } from 'pinia-plugin-unistorage';
export function createApp() {
const app = createSSRApp(App);
const store = Pinia.createPinia();
store.use(createUnistorage());
app.use(store);
return {
app,
Pinia,
};
}以上步骤操作完之后,接下来安装新的持久化插件:pinia-plugin-persistedstate
npm install pinia-plugin-persistedstatepnpm add pinia-plugin-persistedstateyarn add pinia-plugin-persistedstate配置 pinia-plugin-persistedstate 插件,在 src/store/index.ts 中添加以下配置:
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'
const store = createPinia()
store.use(
createPersistedState({
storage: {
getItem: uni.getStorageSync,
setItem: uni.setStorageSync,
},
}),
)
export default store在 src/main.ts 中添加以下配置:
import { createSSRApp } from 'vue'
import store from './store'
export function createApp() {
const app = createSSRApp(App)
app.use(store)
return {
app,
}
}至此,pinia-plugin-persistedstate 插件替换完成。
- 使用示例:
import { defineStore } from 'pinia';
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0);
const doubleCount = computed(() => count.value * 2);
function increment() {
count.value++;
}
return { count, doubleCount, increment };
},
{
persist: true,
},
);iimport { defineStore } from 'pinia'
const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
}
},
persist: true,
})key配置
persist: {
key: "my-key", // 默认为该 store 的 id,这里是 my-key
}paths配置
persist: {
paths: ["count"],
}该 store 中, 只有 count 被持久化。
