兩種方式解決頁面重新整理vuex中資料丟失問題(詳細講解)

語言: CN / TW / HK

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 等...