兩種方式解決頁面重新整理vuex中資料丟失問題(詳細講解)
theme: juejin highlight: a11y-dark
問題描述
首先,關於 頁面重新整理vuex中資料丟失問題
,其實換種方式去描述就是:頁面重新整理vuex中的資料又初始化問題
個人愚見:vuex的資料並不是弄丟了,而是初始化了,回到初始值,回到原點了
關於vuex的用法本篇文章不贅述,詳情可以看之前的文章:http://juejin.cn/post/6965504417764376612
vuex可以理解為是一個公共的空間,所有的元件都可以共享這個空間的狀態資料,大家都可以(修改or讀取)這個空間的資料,但是,這個空間的資料狀態是有初始值的,舉例頁面上的選單資料資訊,因為選單資訊需要儲存在vuex中,作為全域性的共用共享的資料。
- state倉庫中有一個menuArr,初始值為一個空陣列,這個空陣列存放的就是後端傳遞過來的動態選單的陣列資料,關於動態選單可以看上一篇文章:http://juejin.cn/post/7017695269550555167
- 訪問專案初始頁面為登入頁,使用者登入成功以後,會發請求獲取後端返回的動態選單的資料,然後把這個資料存放在vuex中的state中的menuArr裡面,同時進行頁面跳轉到專案首頁
- 這時,頁面上的左側選單欄元件讀取vuex中的menuArr資料並渲染出來,使用者就可以正常操作了。但是!
- 當用戶一重新整理的時候(比如在首頁重新整理),路由不會變,還是在首頁。但是:
無論是 .vue元件中的data中的資料,還是vuex中的state中的資料,都會迴歸到初始狀態。
- 所以vuex中的menuArr陣列又會變成空陣列,又因為vue是響應式的,當menuArr為空陣列的時候,左側選單欄元件就渲染不出來東西,所以就沒了,所以看著就像:
頁面重新整理資料丟失
分析清楚了問題產生的原因,接下來就是想辦法去解決。
解決方案一 本地儲存一份
login頁面
在login.vue元件中的登入中我們去觸發action,請求的介面可以寫在action裡面,也可以寫在元件裡面。這裡因為需要複用action,所以請求我就寫在action裡面了。
```js / login.vue頁面 /
```
vuex中的naviBar模組
```js / vuex中的naviBar模組 /
// 為了發請求,需要有一個vue例項 import Vue from 'vue' const that = new Vue()
/ vuex資料重新整理丟失,解決方案一,本地存一份/
const naviBar = {
state: {
menuArr: JSON.parse(sessionStorage.getItem('menuArr')) ? JSON.parse(sessionStorage.getItem('menuArr')) : []
},
mutations: {
setMenu(state, payload) {
state.menuArr = payload
},
},
actions: {
async getMenu({ commit }, menu) {
let res = await that.$api.getMenuData()
console.log('選單資料', res);
sessionStorage.setItem('menuArr', JSON.stringify(res.data)) // 本地儲存一份
commit("setMenu", res.data) // 提交mutation
},
},
namespaced: true
}
export default naviBar
``
在需要使用vuex中的資料的地方,也就是home.vue首頁的地方,直接使用計算屬性取到相應vuex資料,在html中使用即可。
computed: { menuArr(){ return this.$store.state.naviBar.menuArr } }`
方案分析
此方案解決了問題,但是如果使用者手動把瀏覽器的Application中的sessionstorage中儲存vuex的資料清空,使用者一重新整理還是會丟失,左側的選單還是會沒了。
路人甲:使用者會這樣操作嗎,黑人問號?
所以我們就考慮使用第二種方式,當頁面重新整理的時候,再重新發一次請求即可(不使用瀏覽器儲存了)
解決方案一 頁面重新整理重發請求
login.vue頁面不用動
vuex中的naviBar模組
頁面重新整理重發請求,vuex就不需要寫太複雜了。
```js // 為了發請求,需要有一個vue例項 import Vue from 'vue' const that = new Vue()
/ vuex資料重新整理丟失,解決方案二,再重新發請求 / const naviBar = { state: { menuArr: [] }, mutations: { setMenu(state, payload) { state.menuArr = payload }, }, actions: { async getMenu({ commit }, menu) { let res = await that.$api.getMenuData() commit("setMenu", res.data) }, }, namespaced: true } export default naviBar ```
外層頁面重發請求
注意是外層檢視,這個根據vue專案的檢視結構去選擇位置。我在home.vue中書寫,因為這個頁面也需要使用到vuex中的menuArr資料,也是外層檢視
js
export default {
name: "Home",
created() {
/*
注意由於陣列是引用資料型別,所以 [] 不等於 [] ,這裡轉換成字串進行比較
若vuex中的menuArr不是初始值,就再次發請求重新獲取選單欄的資料
加一個判斷算是優化吧,不加的話,使用者登入的時候會發一次,首頁元件載入的時候也會發一次請求。
即減少請求的傳送次數
*/
if (JSON.stringify(this.$store.state.naviBar.menuArr) == "[]") {
this.$store.dispatch("naviBar/getMenu");
}
},
computed: {
menuArr() {
return this.$store.state.naviBar.menuArr;
},
},
...
};
方案分析
這中方案實現了效果,也減少了本地儲存的使用,不過增加了請求和次數。和上一種方案比較,各有優缺點,具體用那種看業務。
其他方案
還可以使用外掛包去解決,比如 vuex-persistedstate 等...
- vue中使用docx-preview外掛預覽word文件(後端express)
- react元件通訊方式之~圖解父子元件通訊和兄弟元件通訊pubsub-js
- 解決react警告:findDOMNode is deprecated in StrictMode. findDOMNode was passed an...
- vue自定義指令使用~以仿寫v-show和實現v-copy為例講解
- el-table表頭文字換行的三種方式
- elementUI時間日期選擇器更改小圖示的位置和icon
- 兩種方式解決頁面重新整理vuex中資料丟失問題(詳細講解)
- vue元件的遞迴自呼叫~程式碼思路分析
- el-tree樹元件的懶載入寫法步驟