和vuex
种的state类似,都是保存store
的状态
在ts
种会自动推导其类型
tsimport { defineStore } from 'pinia';
export default defineStore(
'userinfoStore',
() => {
const username = ref('');
const rolesname = ref('');
const token = ref('');
return { username, rolesname, token };
},
);
pinia-plugin-persist
实现pnpm i pinia-plugin-persist
tsimport { defineStore } from 'pinia';
export default defineStore(
'userinfoStore',
() => {
const username = ref('');
const rolesname = ref('');
const token = ref('');
return { username, rolesname, token };
},
{
persist: {
enabled: true, // 开启数据缓存
}
}
);
strategies
存储策略
tsinterface PersistStrategy {
key?: string; // 存储的key 默认是 store.$id
//存储方式 localStorage、sessionStorage (默认: sessionStorage)
storage?: Storage;
// 需要持久化的字段名
paths?: string[];
}
tsimport { defineStore } from 'pinia';
export default defineStore(
'userinfoStore',
() => {
const username = ref('');
const rolesname = ref('');
const token = ref('');
return { username, rolesname, token };
},
{
persist: {
enabled: true, // 开启数据缓存
strategies: [
{
// 存储的key
key: 'userinfo',
// 存储方式 localStorage、sessionStorage
storage: sessionStorage,
// 需要持久化的字段名
paths: ['username', 'rolesname', 'token'],
},
],
}
}
);
自定义策略
Storage
的类型
ts/*
* 此Web API接口 提供对sessionStorage和localStorage的访问,允许添加、修改或删除存储的数据项
*/
interface Storage {
/* 返回键值对的数量 */
readonly length: number;
/*
* 如果存在存储的数据就删除全部的
*/
clear(): void;
/*
* 从sessionStorage或localStorage中通过key取值,如果存在则返回,没有则返回 null
*/
getItem(key: string): string | null;
/** 返回第n个键的名称,如果n大于或等于存储中键/值对的数量,则返回null. */
key(index: number): string | null;
/*
* 对于存在的键值对,就通过key删除
*/
removeItem(key: string): void;
/**
* 设置由key/value标识的键/值对的值,如果之前key不存在,则创建一个新的键/值对
* 如果无法设置新值,则抛出“QuotaExceededError”DOMException异常。(设置可能会失败,例如,用户已经禁用了站点的存储,或者如果配额已经超过。)
* key: store.$id,即创建strore时设置的id
* value: 要设置的值,字符串类型
*/
setItem(key: string, value: string): void;
[name: string]: any;
}
tsimport { defineStore } from 'pinia';
const cookiesStorage: Storage = {
setItem(key, state) {
console.log('setItem key state', key, state, typeof state)
/*
setItem key state
userinfoStore
{"rolesname":"EveryOne","token":"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjgxMzA5ODMwLCJleHAiOjE2ODEA2MzB9.ySJZ3CBguR7I9HJJdtCqKri8cRT5EHt3jTpd8jYw"}
string
*/
return sessionStorage.setItem(key, state);
},
getItem(key) {
console.log('getItem key ', key)
return JSON.stringify({
tokens: sessionStorage.getItem(key),
});
},
length: 0,
clear: function (): void {
console.log('clear')
},
key: function (index: number): string | null {
console.log('index', index)
return index.toString()
},
removeItem: function (key: string): void {
console.log('key', key)
}
}
export default defineStore(
'userinfoStore',
() => {
const username = ref('');
const rolesname = ref('');
const token = ref('');
return { username, rolesname, token };
},
{
persist: {
enabled: true, // 开启数据缓存
strategies: [
{
// 存储的key
key: 'userinfo',
// 存储方式 localStorage、sessionStorage
storage: sessionStorage,
// 需要持久化的字段名
paths: ['username', 'rolesname'],
},
{
// 存储方式为自定义的cookiesStorage
storage: cookiesStorage,
// 需要持久化的字段名
paths: ['token'],
},
],
}
}
);
store
目录下新建index.ts
文件
tsimport { createPinia } from 'pinia';
// 数据持久化插件
import piniaPluginPersist from 'pinia-plugin-persist';
const store = createPinia();
// 注册插件
store.use(piniaPluginPersist);
export default store;
main.ts
中配置
import { createApp } from 'vue'; // 引入全局样式文件 import './assets/css/global.less'; import App from './App.vue'; import router from './router'; import store from './pinia'; createApp(App).use(store).use(router).mount('#app');
LoginAndRegister.ts
中使用默认是
sessionStorage
存储,键名为store
的唯一id,值为store的所有状态数据
tsimport { defineStore } from 'pinia';
export default defineStore(
'userinfoStore',
() => {
const username = ref('');
const rolesname = ref('');
const token = ref('');
return { username, rolesname, token };
},
{
persist: {
enabled: true, // 开启数据缓存
strategies: [
{
key: 'userinfo', // 存储的字段名的key
storage: sessionStorage, // 存储方式 localStorage、sessionStorage
paths: ['username', 'rolesname', 'token'], // 需要持久化的字段名
},
],
},
}
);
LoginAndRegister.ts
中使用默认是
sessionStorage
存储,键名为store
的唯一id,值为store的所有状态数据
import { defineStore } from 'pinia'; export const userInfoStroe = defineStore('userinfo', { state: () => { return { username: '', token: '', }; }, persist: { enabled: true, // 开启数据缓存 strategies: [ { storage: localStorage, // 存储方式 localStorage、sessionStorage paths: ['username', 'token'], // 需要持久化的字段名 }, ], }, });
在确保没有丢失响应性
时,可以直接通过修改
vue<template> <div> <div> <input type="text" v-model="name" /> <p>{{ name }}</p> </div> <div> <input type="text" v-model="phone" /> <p>{{ phone }}</p> </div> <div> <button @click="changeName">直接赋值修改name</button> </div> </div> </template> <script setup lang="ts"> import userinfoStore from '@/stores/userinfo.js'; import { storeToRefs } from 'pinia'; const userStore = userinfoStore(); const { name, phone } = storeToRefs(userStore); function changeName(){ name.value = 'xm' } </script>
通过.$patch()
实现,可以接受一个对象修改部分state
,或者接受一个函数批量修改集合内部分对象的情况
如果直接传入一个对象,则对于state中的任何集合修改(EG:数组中推送、删除、拼接元素)都需要创建一个新集合
vue<template> <div> <div> <input type="text" v-model="name" /> <p>{{ name }}</p> </div> <div> <input type="text" v-model="phone" /> <p>{{ phone }}</p> </div> <div> <button @click="changeName">直接赋值修改name</button> <button @click="changePatchObj">patchObj修改</button> <button @click="changePatchFn">patchFn修改</button> <button @click="resertUser">重置</button> </div> </div> </template> <script setup lang="ts"> import userinfoStore from '@/stores/userinfo.js'; import { storeToRefs } from 'pinia'; const userStore = userinfoStore(); const { name, phone } = storeToRefs(userStore); function resertUser() { userStore.$reset(); } function changeName() { name.value = 'xm'; } function changePatchObj() { userStore.$patch({ name: 'xm', phone: '123344', }); } function changePatchFn() { userStore.$patch((state)=>{ console.log('state', state) // state.name = 'xk' }); } </script>
store.$state
设置为新对象来替换整个state
的状态store.state.value
设置为新对象替换整个state
的状态tsuserStore.$state = {name:'xm',phone:'1212'}
userStore.state.value = {name:'xm',phone:'1212'}
通过.$reset()
实现
在OptionsStore
中可以直接使用
在组合式API创建的Store
中不能直接使用,会报错
tsUncaught Error: 🍍: Store "userinfo" is built using the setup syntax and does not implement $reset().
at Proxy.$reset (pinia.mjs:1326:27)
at resertUser (AboutView.vue:80:2)
at callWithErrorHandling (runtime-core.esm-bundler.js:173:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:182:21)
at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:345:9)
自定义pinia
插件重写$reset
方法,需要借助lodash.clonedeep
深度克隆
lodash.clonedeep
tspnpm install lodash.clonedeep -S
utils/common/storeUtils/
创建StoreReset.ts
文件tsimport cloneDeep from 'lodash.clonedeep';
export default function storeReset({ store }) {
// 深度克隆初始状态
const initialState = cloneDeep(store.$state);
// 将`$reset`方法挂载到store实例上,然后通过store.$patch批量修改state
store.$reset = () => store.$patch(cloneDeep(initialState));
}
store/index.ts
中注册插件tsimport storeReset from '@/utils/common/storeUtils/StoreReset';
import { createPinia } from 'pinia';
const store = createPinia();
// 注册插件
store.use(storeReset);
export default store;
可以通过.$subscribe()
方法或vue
的watch()
方法
.$subscribe()
的优点: subscriptions
只会在patches
之后触发一次(例如,当使用上面的函数版本时) ---暂未理解,个人尝试好像都会触发
默认情况下绑定的组件被卸载后,如果需要在组件卸载后保留,需要使用{ detached: true }
作为.$subscribe
的第二个参数传入
vue<template> <div> <div> <input type="text" v-model="name" /> <p>{{ name }}</p> </div> <div> <input type="text" v-model="phone" /> <p>{{ phone }}</p> </div> <div> <button @click="changeName">直接赋值修改name</button> <button @click="changePatchObj">patchObj修改</button> <button @click="changePatchFn">patchFn修改</button> <button @click="resertUser">重置</button> </div> </div> </template> <script setup lang="ts"> import { ref, watch } from 'vue'; import userinfoStore from '@/stores/userinfo.js'; import { storeToRefs } from 'pinia'; const userStore = userinfoStore(); const { name, phone } = storeToRefs(userStore); function resertUser() { userStore.$reset(); } function changeName() { name.value = 'xm'; } function changePatchObj() { userStore.$patch({ name: 'xm', phone: '123344', }); } function changePatchFn() { userStore.$patch((state)=>{ console.log('state', state) }); } userStore.$subscribe((mutation, state) => { console.log('mutation, state', mutation, state) // import { MutationType } from 'pinia' /* mutation.type 'direct': 直接修改 'patch object': 通过`$patch()`传入参数为Object 'patch function': 通过`$patch()`传入参数为函数 */ // 与 cartStore.$id 相同 mutation.storeId // 'userinfo' // 只在 mutation.type === 'patch object' 才具备 mutation.payload // 每当它发生变化时,将整个状态持久化到本地存储 localStorage.setItem('test1', JSON.stringify(state)) }) watch( userStore.$state, (state) => { console.log('watch ', state) // 每当它发生变化时,将整个状态持久化到本地存储 localStorage.setItem('test2', JSON.stringify(state)) }, { deep: true } ) </script>
$patch
传入对象$patch
传入函数本文作者:RKLS
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!