淺談vuex 閑置狀態(tài)重置方案
前言
大型單頁應(yīng)用(后面都是指spa),我們往往會通過使用狀態(tài)管理器 vuex 去解決組件間狀態(tài)共享與狀態(tài)傳遞等問題。這種應(yīng)用少則幾十個(gè)單頁,多則上百個(gè)單頁。隨著路由的頻繁切換,每個(gè)路由對應(yīng)的 vuex 中的狀態(tài)將越來越多。為了做到頁面的極致優(yōu)化,我們需要將那些閑置的狀態(tài)重置,以減小占用的內(nèi)存空間。
什么狀態(tài)可以重置
vuex 強(qiáng)調(diào)采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),但是我們真把所有的狀態(tài)都放到 store 中去處理,你會發(fā)現(xiàn)開發(fā)起來非常痛苦。這里如果想很好的把控哪些數(shù)據(jù)需要放到 store 中去管理,首先要理解 vuex 是用來解決什么問題的。vuex 官網(wǎng)指出是為了解決 多個(gè)組件共享狀態(tài) 的,那么我們就可以把多個(gè)組件的共享狀態(tài)放到 store 中去管理,這里的多組件共享對于單頁應(yīng)用很多情況是跨路由的組件。如果 store只存儲多組件共享的狀態(tài),那么我們就沒必要去清理 vuex 中的狀態(tài)了,因?yàn)檫@些狀態(tài)隨時(shí)會被用到。
而隨著業(yè)務(wù)場景越來越復(fù)雜,很多與后臺交互的邏輯也都放到了組件中,這樣代碼就變得很凌亂,vuex 也沒有被充分利用。這時(shí)我們可以把與后臺 api 交互的邏輯放到 vuex 中的action 去處理,后臺返回的狀態(tài)自然也就放到了 store 管理。這樣處理后,組件就只負(fù)責(zé)對數(shù)據(jù)進(jìn)行渲染,邏輯非常清晰。而此時(shí),組件對應(yīng)的 store 中的狀態(tài)隨著路由的切換將會越來越多,而這些狀態(tài)就需要我們手動的去清理了。
很多方案都有取舍,如果將與后臺 api 交互的數(shù)據(jù)放到組件中,就沒必要去清理了,但是代碼邏輯將變得比較亂。另外諸如 vuex 的插件vue-devtools 將無法監(jiān)控到每次請求數(shù)據(jù)的變化...
什么時(shí)候去重置狀態(tài)
我們想要的效果是在路由切換的時(shí)候,把上一個(gè)路由對應(yīng)的 vuex 中的狀態(tài)重置掉,但是路由和vuex 并沒有一一對應(yīng)的關(guān)系,如果要做到這種效果,那么我們需要維護(hù)一個(gè)路由與vuex 模塊的對應(yīng)關(guān)系,這樣會很繁瑣。不如當(dāng)路由改變時(shí)去重置 vuex 中的所有狀態(tài)。
vuex 中閑置狀態(tài)如何清理
下面將結(jié)合我的github實(shí)例 去說明,這個(gè)實(shí)例創(chuàng)建了一個(gè)單頁應(yīng)用,我們通過切換路由的時(shí)候?qū)㈤e置的狀態(tài)清除。
改造路由對應(yīng)組件的 module 狀態(tài)
實(shí)例中采用拆分 store 為多個(gè) module 的方式,將路由對應(yīng)的組件狀態(tài)放到對應(yīng)的 module 中,多組件共享的狀態(tài)放到頂級的 store 中管理。大致如下:
// store/index.js
import page1 from "./modules/page1.js";
import page2 from "./modules/page2.js";
import page3 from "./modules/page3.js";
import page4 from "./modules/page4.js";
import page5 from "./modules/page5.js";
export default new Vuex.Store({
state,
getters,
actions,
mutations,
modules: { // 每個(gè)路由對應(yīng)的 module
page1,
page2,
page3,
page4,
page5
},
plugins: __DEV__ ? [createLogger()] : [],
strict: __DEV__ ? true : false
});
路由 page1 對應(yīng)的 module 的 state 形如:
// store/modules/page1.js
const state = {
// 列表數(shù)據(jù)
page1Data: [],
// 標(biāo)題數(shù)據(jù)
page1Title: ''
}
這些數(shù)據(jù)是通過調(diào)用后端 api 返回并復(fù)制的數(shù)據(jù),如果我們在路由改變的時(shí)候重置這些數(shù)據(jù),那么需要將初始化數(shù)據(jù)提取出來,并且暴露一個(gè)需要重置的標(biāo)識方法 initState() ,代表路由改變的時(shí)候需要重置,當(dāng)然這個(gè)方法名稱是個(gè)約定,你也可以定義為其他名稱。改造后為:
// store/modules/page1.js
// 放置你要重置的數(shù)據(jù)
const initState = {
page1Data: [],
}
// state
const state = {
// 參數(shù)解構(gòu)
...initState,
// 路由改變不想重置的數(shù)據(jù)
page1Title: '',
initState(){
return initState
}
}
全局 module 配置
定義全局 mutation 事件類型
// store/types.js export const RESET_STATES = 'resetStates'
定義全局 mutation
// store/mutation.js
import * as types from './types'
// 檢測所有的 state 并把 `initState()` 中的屬性重置
function resetState(state, moduleState) {
const mState = state[moduleState];
if (mState.initState && typeof mState.initState === 'function') {
const initState = mState.initState();
for (const key in initState) {
mState[key] = initState[key];
}
}
}
export default {
[types.RESET_STATES](state, payload) {
for (const moduleState in state) {
resetState(state, moduleState);
}
},
}
定義全局 action
// store/action.js
import * as types from './types'
export default {
// rest state action
resetStates:function (context, payLoad) {
context.commit(types.RESET_STATES, payLoad);
}
}
路由切換觸發(fā)重置方法
至此一切準(zhǔn)備就緒,只需要在路由改變時(shí)觸發(fā)重置的方法即可,在入口 vue 文件中處理
// components/app.vue
<script>
import {mapState, mapActions} from "vuex"
export default{
methods: {
...mapActions({
resetStates: "resetStates"
})
},
watch: {
$route(to, from) {
// 路由改變發(fā)起重置
this.resetStates();
}
}
}
</script>
如果你的 chrome 瀏覽器安裝了vuejs-devtools 在路由切換的時(shí)候就能夠很清晰的看到上一個(gè)路由數(shù)據(jù)的的重置過程。
總結(jié)
實(shí)例點(diǎn)這里 。我們這里的 vuex 狀態(tài)重置,是每次路由切換遍歷所有的 store 中的狀態(tài),并把 initState() 中的屬性重置,如果能做到把當(dāng)前的路由對應(yīng)的 state 重置就更好了,但是路由和 store 中的 module 并沒有關(guān)聯(lián)關(guān)系。這里只是提供一種重置 vuex 狀態(tài)的一種方案,如果有更好方案還請各位看官留言。如有不妥的地方也歡迎拍磚留言。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue+ElementUi實(shí)現(xiàn)點(diǎn)擊表格中鏈接進(jìn)行頁面跳轉(zhuǎn)與路由詳解
在vue中進(jìn)行前端網(wǎng)頁開發(fā)時(shí),通常列表數(shù)據(jù)用el-table展示,下面這篇文章主要給大家介紹了關(guān)于Vue+ElementUi實(shí)現(xiàn)點(diǎn)擊表格中鏈接進(jìn)行頁面跳轉(zhuǎn)與路由的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
基于Vue2實(shí)現(xiàn)數(shù)字縱向滾動效果
這篇文章主要為大家詳細(xì)介紹了如何基于Vue2實(shí)現(xiàn)數(shù)字縱向滾動效果,從而達(dá)到顯示計(jì)時(shí)器滾動效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
Monaco?Editor開發(fā)SQL代碼提示編輯器實(shí)例詳解
這篇文章主要為大家介紹了Monaco?Editor開發(fā)SQL編輯器實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
關(guān)于vue v-for 循環(huán)問題(一行顯示四個(gè),每一行的最右邊那個(gè)計(jì)算屬性)
這篇文章主要介紹了關(guān)于vue v-for 循環(huán)問題(一行顯示四個(gè),每一行的最右邊那個(gè)計(jì)算屬性),需要的朋友可以參考下2018-09-09
vue3+ts+MicroApp實(shí)戰(zhàn)教程
這篇文章主要介紹了vue3+ts+MicroApp實(shí)戰(zhàn)教程,分別在主應(yīng)用項(xiàng)目(main)和子應(yīng)用(childrenOne,childrenTwo)項(xiàng)目中安裝microApp,本文給大家詳細(xì)講解,需要的朋友可以參考下2022-10-10

