手機(jī)網(wǎng)站開發(fā) caso平臺
vue3-vuex持久化實(shí)現(xiàn)
- 一、背景描述
- 二、實(shí)現(xiàn)思路
- 1.定義數(shù)據(jù)結(jié)構(gòu)
- 2.存值
- 3.取值
- 4.清空
- 三、具體代碼
- 1.定義插件
- 2.使用插件
- 四、最終效果
一、背景描述
有時候我們可能需要在vuex中存儲一些靜態(tài)數(shù)據(jù),比如一些下拉選項(xiàng)的字典數(shù)據(jù)。這種數(shù)據(jù)基本很少會變化,所以我們可能希望將其存儲起來,這樣就減少了請求的數(shù)量。
但是在每個位置都進(jìn)行存儲,好像是在做重復(fù)的邏輯,所以我們可以考慮將這個功能提取出來,作為一個插件使用。
注意:建議不要濫用持久化存儲,因?yàn)檫@可能導(dǎo)致你不能獲取到最新的數(shù)據(jù),只建議在一些長期不會變化的數(shù)據(jù)中使用。
二、實(shí)現(xiàn)思路
做到持久化存儲,那就要在頁面銷毀之前將值存到storage中,頁面初始化的時候,再將值取到vuex中進(jìn)行數(shù)據(jù)初始化
1.定義數(shù)據(jù)結(jié)構(gòu)
我們首先要規(guī)定哪些值需要存儲,因?yàn)槲覀儧]必要持久化存儲大部分的vuex數(shù)據(jù),所以沒必要進(jìn)行全量存儲。
我這里將數(shù)據(jù)結(jié)構(gòu)定義為數(shù)組:
const storageItem = [{storageType: 'local', // 存儲類型:local或者sessionstorageKey: 'name', // 存儲的keystorageValue: () => Store.getters.getName || '', // 需要存儲的值,也可以用 () => Store.state.name 這種形式storeMutations: 'SET_NAME' // vuex設(shè)置值時的mutations,用于頁面刷新完成之后初始化vuex}
]
每多一個需要持久化存儲的內(nèi)容,就增加一個元素即可。
2.存值
在頁面銷毀前存值我們可以直接在window的beforeunload回調(diào)中進(jìn)行即可
window.addEventListener('beforeunload', () => {storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragestorage.setItem(item.storageKey, item.storageValue())})})
也可以在vue組件的onUnmounted回調(diào)中進(jìn)行存儲,但是這樣就需要你在vue組件中執(zhí)行這個邏輯了。當(dāng)然你也可以考慮將邏輯封裝為hooks。
3.取值
在頁面渲染前從storage中取到值,并且初始化vuex。
有一點(diǎn)可能要注意,我們從后端獲取一些全局?jǐn)?shù)據(jù)時,一般會在routerBeforeEach中進(jìn)行接口調(diào)用。所以不建議在window的load回調(diào)中調(diào)用。我們執(zhí)行初始化盡量在routerBeforeEach之前執(zhí)行,這樣我們就可以判斷vuex如果存在值,就不用再調(diào)用接口了。
我這里在main.js中調(diào)用插件時執(zhí)行:
storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragelet storageValue = storage.getItem(item.storageKey)try {storageValue = JSON.parse(storageValue as string)} catch {}if (storageValue) {if (item.storeMutations) {Store.commit(item.storeMutations, storageValue)}}})
4.清空
我們可以提供一個清空的方法,便于某些時候清空所有的存儲(如果擔(dān)心數(shù)據(jù)時效性,可以設(shè)置一個時間,超出這個時間段之后就全部清空)
storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragestorage.removeItem(item.storageKey)})
三、具體代碼
1.定義插件
新建一個storeStorage.js
import Store from '@/store'
/*** 統(tǒng)一移除存儲的vuex數(shù)據(jù)*/
export const removeStoreStorage = () => {storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragestorage.removeItem(item.storageKey)})
}
// 持久化存儲相應(yīng)vuex數(shù)據(jù)
const storageItem = [{storageType: 'local', // 存儲類型:local或者sessionstorageKey: 'name', // 存儲的keystorageValue: () => Store.getters.getName || '', // 需要存儲的值storeMutations: 'SET_NAME' // vuex設(shè)置值時的mutations,用于頁面刷新完成之后初始化vuex}
]
export default {install() {this.getStoreStorage()this.setStoreStorage()},/*** 頁面銷毀前,存儲數(shù)據(jù)*/setStoreStorage() {window.addEventListener('beforeunload', () => {storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragestorage.setItem(item.storageKey, item.storageValue())})})},/*** 頁面刷新時,重新加載存儲的vuex數(shù)據(jù)*/getStoreStorage() {storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragelet storageValue = storage.getItem(item.storageKey)try {storageValue = JSON.parse(storageValue as string)} catch {}if (storageValue) {if (item.storeMutations) {Store.commit(item.storeMutations, storageValue)}}})}
}
2.使用插件
在main.js
中引入,并使用
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import storeStorage from '@/util/storeStorage'
import store from './store'
const app = createApp(App)
app.use(store).use(router).use(storeStorage).mount('#app')
其中vuex中index.js
定義:
import { createStore } from 'vuex'export default createStore({state: {name: '',age: ''},getters: {getName: state => state.name,getAge: state => state.age},mutations: {SET_NAME(state, name) {state.name = name},SET_AGE(state, age) {state.age = age}},actions: {},modules: {}
})
四、最終效果
app.vue
中
<template><input type="text" v-model="$store.state.name"/>
</template><style lang="scss">
#app {color: #2c3e50;
}
</style>
<script setup lang="ts">
</script>
輸入內(nèi)容再刷新頁面就會發(fā)現(xiàn)值被緩存了。
注:插件、routerBeforeEach和window.load執(zhí)行順序
router.beforeEach((to, from, next) => {console.log('routerBeforeEach')next()
})
window.addEventListener('load', () => {console.log('load')
})
插件中的部分代碼
/*** 頁面刷新時,重新加載存儲的vuex數(shù)據(jù)*/getStoreStorage() {storageItem.forEach(item => {const storage =item.storageType === 'session' ? sessionStorage : localStoragelet storageValue = storage.getItem(item.storageKey)try {storageValue = JSON.parse(storageValue as string)} catch {}if (storageValue) {if (item.storeMutations) {Store.commit(item.storeMutations, storageValue)}}})console.log('getStoreStorage')}
執(zhí)行結(jié)果: