1、pinia官网:pinia.web3doc.top/introductio…
2、持久化插件pinia-plugin-persist官网:seb-l.github.io/pinia-plugi…
一、定义
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 Store有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。
二、使用
npm install pinia
npm install pinia-plugin-persist //持久化插件
src/stores/index.ts
import {createPinia} from 'pinia'
//pinia持久化插件
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPluginPersist)
export default store
main.ts
import { createApp } from 'vue'
import pinia from '@/stores'
const app = createApp(App)
app.use(pinia)
app.mount('#app')
src/stores/userInfo.ts
import { defineStore } from 'pinia'
export const userInfoStore = defineStore('userInfo',{
state:()=>{
return{
personId:"",
personName:""
}
},
actions:{
setPersonId(value:string){
this.personId = value
},
setPersonName(value:string){
this.personName = value
}
},
//开启数据持久化缓存 默认`sessionStorage` 储存
persist:{
enabled:true,
strategies:[
{
storage:localStorage,//存储方式
paths:["personId","personName"]//存储属性
}
]
}
})
login.ts
import {userInfoStore} from '@/stores/userInfo'
const userStore = userInfoStore()
const doLogin = async()=>{
const res = await api.get("/api/toLogin")
console.log("res:",res)
let data = res.data;
if(data.code === 200){
let loginConfig = data.data;
let personId = loginConfig.person_id;
let personName = loginConfig.person_name;
userStore.setPersonId(personId)
userStore.setPersonName(personName)
router.push("/")
}
}
三、源码解读
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)
})
})
}
}
四、pinia与vuex的区别
1、pinia没有mutation,只有state,getters,action[同步、异步]使用它来修改state数据
2、pinia没有modules配置,每一个独立的仓库都是defineStore生成出来的
五、pinia和vuex的优缺点
Pinia优点:
- 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
- 极其轻巧(体积约 1KB)
- store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
- 支持多个Store
- 支持 Vue devtools、SSR 和 webpack 代码拆分
Pinia的缺点
- 不支持时间旅行和编辑等调试功能
Vuex的优点
- 支持调试功能,如时间旅行和编辑
- 适用于大型、高复杂度的Vue.js项目
Vuex的缺点
- 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
- Vuex 4有一些与类型安全相关的问题
何时使用Pinia,何时使用Vuex
个人感觉:,由于Pinea是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
将 Vuex 用于中小型 Vue.js 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目。