(一)API
1.$reset
重置store到他的初始状态
初始值
state: () => ({
user: <Result>{},
name: "default",
current:1
}),
改变初始值
const change = () => {
Test.current++
}
调用$reset(), 将会把state所有值 重置回 原始状态
2.订阅state的改变
类似于Vuex 的abscribe 只要有state 的变化就会走这个函数
Test.$subscribe((args,state)=>{
console.log(args,state);
})
第二个参数
如果你的组件卸载之后还想继续调用请设置第二个参数
Test.$subscribe((args,state)=>{
console.log(args,state);
},{
detached:true
})
3.订阅Actions的调用
只要有actions被调用就会走这个函数
Test.$onAction((args)=>{
console.log(args);
},true) //第二个参数是在组件被销毁还想监听这个$onAction的时候开启
(二)pinia持久化
在某些特定的单页面应用场景下,我们使用常规的 store 来存储数据,很多时候面临着刷新就会被重置,所以,我们急需一个插件功能来实现对某些特定的数据进行状态保持。
这里我们很容易想到可以用 sessionStorage 或者 localStorage 来进行相应的处理,但是要对不同的 store 中不同的字段进行处理,也是有很大的心智负担。
这里我推荐一款 Pinia 的持久化插件:pinia-plugin-persist
点击 插件官方文档
他提供了简便的使用方式以及灵活的配置方式,下面我就和大家分享一下这款插件的使用方式及实现原理。
安装插件
# npm
npm install pinia-plugin-persist
# yarn
yarn add pinia-plugin-persist
# pnpm
pnpm add pinia-plugin-persist
配置文件在main.js中直接引入太过于冗余,我们重新建一个文件在store文件夹下新建xx.js:
// pluginPersist.js文件夹下
import { createPinia } from 'pinia'
// 引入持久化插件
import piniaPluginPersist from 'pinia-plugin-persist'
const pinia = createPinia()
// 使用该插件
pinia.use(piniaPluginPersist)
//导出
export default pinia
在main,js中全局导入
//main.js文件夹下
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import pinia from './stores/pluginPersist' //这里引入
import './assets/main.css'
const app = createApp(App)
app.use(createPinia()).use(pinia) //这里挂载
app.mount('#app')
然后在pinia的模块写:persist
import { defineStore } from 'pinia'
export const useNameStore = defineStore('Name', {
state: () => {
return {
name: '小1111李',
age: '18',
tokens:'hsdjksdhsdds'
}
},
getters: { // computed 修饰一些值
},
actions: { // methods 可以做同步 异步都可以做 提交到state
changeName () {
this.name = '我修改了名字'
console.log(this);
},
changeAge () {
setTimeout(() => {
this.age = 10000
}, 3000)
},
},
//添加如下配置
persist: {
// 开启持久化
enabled: true,
// 选择存储方式和内容
strategies: [
{
key: "tokenToKen", // 自定义存储的 key,默认是 store.$id
storage: localStorage, // 可以指定任何 extends Storage 的实例,默认是 sessionStorage
paths: ['name', 'age', 'tokens'] // state 中的字段名,按组打包储存
},
]
}
})
storage自定义存储:
storage 属性可以使用任何继承自 Storage 协议的对象,自定义存储对象也可以,如下 cookiesStorage 为例
import Cookies from 'js-cookie'
const cookiesStorage: Storage = {
setItem (key, state) {
return Cookies.set('accessToken', state.accessToken, { expires: 3 })
},
getItem (key) {
return JSON.stringify({
accessToken: Cookies.getJSON('accessToken'),
})
},
}
export const useStore = defineStore("YourStore", () => {
const foo = ref("foo")
const bar = ref("bar")
const accessToken = ref("xxx")
return { foo, bar, accessToken }
}, {
enabled: true,
strategies: [{
key: "token",
storage: cookiesStorage,
paths: ["accessToken"]
}]
})
插件核心功能源码解读
type Store = PiniaPluginContext['store'];
type PartialState = Partial<Store['$state']>;
export const updateStorage = (strategy: PersistStrategy, store: Store) => {
// 默认使用 sessionStorage
const storage = strategy.storage || sessionStorage
// 默认存储 key 为 store.$id
const storeKey = strategy.key || store.$id
if (strategy.paths) {
// 遍历 paths 将对应的属性收集到 finalObj 中
const partialState = strategy.paths.reduce((finalObj, key) => {
finalObj[key] = store.$state[key]
return finalObj
}, {} as PartialState)
// 执行存储
storage.setItem(storeKey, JSON.stringify(partialState))
} else {
// 如果没有 paths,则按整个 store.$state 存储
storage.setItem(storeKey, JSON.stringify(store.$state))
}
}
export default ({ options, store }: PiniaPluginContext): void => {
// 判断插件功能是否开启
if (options.persist?.enabled) {
// 默认策略实例
const defaultStrat: PersistStrategy[] = [{
key: store.$id,
storage: sessionStorage,
}]
const strategies = options.persist?.strategies?.length ? options.persist?.strategies : defaultStrat
strategies.forEach((strategy) => {
const storage = strategy.storage || sessionStorage
const storeKey = strategy.key || store.$id
const storageResult = storage.getItem(storeKey)
if (storageResult) {
// 如果 storage 中存在同步数据
store.$patch(JSON.parse(storageResult))
updateStorage(strategy, store)
}
})
store.$subscribe(() => {
// 监听 state 变化,同步更新 storage
strategies.forEach((strategy) => {
updateStorage(strategy, store)
})
})
}
}