在开发的过程当中我们会遇到仓库持久化的问题,今天给大家分享一下仓库持久化的基本用法和原理,状态管理库有两种一种是Vuex,一种是Pinia,两种都分享一下。
仓库持久化有专门的插件可以使用,此篇文章没有采用插件,而是用了自定义的函数插件来实现的供大家参考
此文章以vue3为例,UI组件用的是Naive UI
Vuex
创建vuex仓库
下载并配置vuex
//这里的 @next 是为了安装 Vuex 4,它适用于 Vue 3。
pnpm add vuex@next
配置Vuex仓库
下载完成后配置仓库,在main.ts引入vuex
//main.ts
import { createApp } from 'vue'
import vuex from './storeVuex/index'
const app = createApp(App)
app.use(vuex).mount('#app')
在src下创建文件夹 storeVuex,以及存放模块的modules文件夹和一些ts文件,这是Vuex仓库的目录结构
小仓库 user.ts
//user.ts
const user = {
namespaced: true,
state: {
name: '周杰伦',
age: 35,
role: '歌手',
},
mutations: {
setName(state, newName) {
state.name = newName
},
setAge(state, newAge) {
state.age = newAge
},
setRole(state, newRole) {
state.role = newRole
},
},
actions: {
updateName({ commit }, newName) {
commit('setName', newName)
},
updateAge({ commit }, newAge) {
commit('setAge', newAge)
},
//修改State中的值
update({ commit }, payload) {
commit('setName', payload.name)
commit('setAge', payload.age)
commit('setRole', payload.role)
},
},
}
export default user
在大仓库中引入小仓库 index.ts
//index.ts
import { createStore } from 'vuex'
import user from './modules/user'
//这里引入我们自定义的插件,其实就是一个函数
import myPlugin from './myPlugin.ts'
const store: any = createStore({
modules: {
test: user,
},
//plugin的执行时机是在仓库初始化完成之后调用
plugins: [myPlugin],
})
export default store
编写插件函数
自定义插件 myPlugin.ts
编写我们的插件函数。
//myPlugin.ts
const myPlugin = (store) => {
//store 是仓库对象
//存储数据
//beforeunload事件——用户正在离开
window.addEventListener('beforeunload', (e) => {
localStorage.setItem('USER', JSON.stringify(store.state))
})
// 取数据
const user = localStorage.getItem('USER')
if (user) {
store.replaceState(JSON.parse(user))
}
}
export default myPlugin
使用仓库
在页面中使用store
<template>
<div>
<div class="store-container">
<h2>vuex</h2>
<n-form
ref="formRef"
inline
label-width="auto"
label-placement="left"
:model="formJay"
:size="size"
>
<n-form-item label="姓名" path="name">
<n-input v-model:value="formJay.name" placeholder="输入姓名" />
</n-form-item>
<n-form-item label="年龄" path="age">
<n-input v-model:value="formJay.age" placeholder="输入年龄" />
</n-form-item>
<n-form-item label="角色" path="role">
<n-input v-model:value="formJay.role" placeholder="角色" />
</n-form-item>
<n-form-item>
<n-button type="primary" attr-type="button" @click="updateJay">
提交
</n-button>
</n-form-item>
</n-form>
</div>
</div>
</template>
<script lang="ts" setup>
import { useStore } from 'vuex'
import { onMounted, ref } from 'vue'
const userStore = useStore()
const formRef = ref<any>()
const size = ref<'small' | 'medium' | 'large'>('medium')
//取值
const formJay = ref<any>({
name: undefined,
age: undefined,
role: undefined,
})
const updateJay = () => {
//更新数据
userStore.dispatch('user/update', formJay.value)
}
onMounted(() => {
//取值 赋值
formJay.value = userStore.state.user
})
</script>
<style lang="scss" scoped>
.store-container {
width: 100%;
height: 400px;
//text-align: center;
margin-top: 100px;
h2 {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
}
}
</style>
查看状态
修改完数据之后——点击提交,然后刷新页面,数据不会丢失,说明仓库状态持久化成功了
我们是将数据存储在了 localStorage,所以要在localstorage中查看数据是否保存成功,USER是在插件函数中 监听beforeunload
存的值
Pinia
创建Pinia仓库
pnpm add pinia
配置Pinia仓库
myPlugin是自己编写的插件函数
//main.ts
import { createApp } from 'vue'
import pinia from './store'
//pinia使用自定义插件
import piniaPlugin from './store/myPlugin'
pinia.use(piniaPlugin)
const app = createApp(App)
app.use(pinia).mount('#app')
在src下创建文件夹 store,以及存放模块的modules文件夹和一些ts文件,这是Pinia仓库的目录结构
创建小仓库 user.ts
//user.ts
import { defineStore } from 'pinia'
const useUserStore = defineStore('User', {
state: () => ({
name: '林俊杰',
age: 35,
role: '歌手',
}),
actions: {
updateName(newName) {
this.name = newName
},
updateAge(newAge) {
this.age = newAge
},
update({ name, age, role }) {
this.name = name
this.age = age
this.role = role
},
},
})
export default useUserStore
创建大仓库 index.ts
//index.ts
import { createPinia } from 'pinia'
import { useUserStore } from './modules/user'
//创建大仓库
const pinia = createPinia()
//对外暴露:入口文件需要安装仓库
export default pinia
编写插件函数
Pinia的context和vuex不同,Pinia在使用的时候接收到的 context是仓库的上下文,每个仓库有自己的上下文,通过在控制台的输出可以看到 store中的$id 可以区分出来是哪个仓库,所以我们在往localStorage中存数据的时候,可以通过$id的值做区分
//myPlugin.ts
const KEY = 'PINIA_STORE_'
const myPlugin = (context) => {
console.log(context)
const { store } = context
const KEY_ = KEY + store.$id
window.addEventListener('beforeunload', (e) => {
localStorage.setItem(KEY_, JSON.stringify(store.$state))
})
const user = localStorage.getItem(KEY_)
if (user) {
store.$patch(JSON.parse(user))
}
}
export default myPlugin
使用仓库
在页面使用仓库
<template>
<div>
<div class="store-container">
<h2>pinia</h2>
<n-form
ref="formRef"
inline
label-width="auto"
label-placement="left"
:model="formJJ"
:size="size"
>
<n-form-item label="姓名" path="name">
<n-input v-model:value="formJJ.name" placeholder="输入姓名" />
</n-form-item>
<n-form-item label="年龄" path="age">
<n-input v-model:value="formJJ.age" placeholder="输入年龄" />
</n-form-item>
<n-form-item label="角色" path="role">
<n-input v-model:value="formJJ.role" placeholder="角色" />
</n-form-item>
<n-form-item>
<n-button type="primary" attr-type="button" @click="updateJJ">
提交
</n-button>
</n-form-item>
</n-form>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import useUserStore from '@/store/modules/user'
const formRef = ref<any>()
const userStore = useUserStore()
const size = ref<'small' | 'medium' | 'large'>('medium')
const formJJ = ref<any>({
name: undefined,
age: undefined,
role: undefined,
})
onMounted(() => {
//取值
formJJ.value = userStore.$state
})
const updateJJ = () => {
//修改值
userStore.update(formJJ.value)
}
</script>
<style lang="scss" scoped>
.store-container {
width: 100%;
height: 400px;
margin-top: 100px;
h2 {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 20px;
}
}
</style>
查看状态
修改完数据之后——点击提交,然后刷新页面,数据不会丢失,说明仓库状态持久化成功了
我们是将数据存储在了 localStorage,所以要在localstorage中查看数据是否保存成功,PINIA_STORE_User 是在插件函数中 监听beforeunload
存的值
完结 !!!