用Vue作項目開發好久了,對於vuex能用、會用,可是由於狀態脫離頁面和刷新丟失兩個緣由,一直都有種抵觸,特別是一些簡單的數據都是經過query或者本地存儲就解決了,然而對於一些複雜內容,不可避免的仍是要使用Vuex去處理(真香),可是刷新丟失的問題,的確叫人頭大。最近閒下來,咱們來研究下怎麼幹掉這個問題~javascript
不大瞭解Vuex的同窗,能夠先去官網溜溜vue
因爲Vuex的數據是存儲在內存中的,至關於memory cache,當頁面刷新的時候內存被清空重載新內容,原來的數據就丟了,爲了解決這個咱們能夠藉助瀏覽器的本地存儲來解決,此時咱們有兩個選擇java
相比之下localStorage太持久了,不主動清除都會一直在,而sessionStorage更符合Vuex會話期狀態管理的設計初衷。所以下文中統一使用sessionStorage來作補充,解決問題。vuex
有了補充對象以後,咱們要作的只有兩點
一、每次在mutation中set state的時候,同步的塞到sessionStorage一份
二、狀態初始化的時候,從sessionStorage中讀取相應內容並做爲默認值(存在的話)npm
看起來很簡單,因而初版方案有了,數組
export default new Vuex.Store({ state: { userLevel: sessionStorage.getItem('userLevel') || '' }, mutations: { SET_USERLEVEL(state, userLevel) { sessionStorage.setItem('userLevel', userLevel) state.userLevel = userLevel } }, modules: { } })
這個是解決問題了,可是每一個mutation都要sessionStorage.setItem一下實在有點麻煩,並且初始化還要都getItem一遍,我很懶不想寫。。。因而咱們改進了第二版瀏覽器
const storeMaker = (state) => { // 初始化 Object.keys(state).map((key) => { // 判斷類型獲取本地存儲數據 if (typeof state[key] === 'object') { if (sessionStorage.getItem(key) && JSON.parse(sessionStorage.getItem(key))) { state[key] = JSON.parse(sessionStorage.getItem(key)) } } else if (typeof state[key] === 'number') { if (sessionStorage.getItem(key) && parseInt(sessionStorage.getItem(key))) { state[key] = parseInt(sessionStorage.getItem(key)) } } else { if (sessionStorage.getItem(key)) { state[key] = sessionStorage.getItem(key) } } }) // 重寫set處理 return new Proxy(state, { set: function(target, key, value) { let temp = value if (typeof temp === 'object') { temp = JSON.stringify(temp) } sessionStorage.setItem(key, temp) return Reflect.set(target, key, value) } }) } export default new Vuex.Store({ state: storeMaker({ userLevel: '' }), mutations: { SET_USERLEVEL(state, userLevel) { state.userLevel = userLevel } }, modules: { } })
內容很少,主要定義了一個storeMaker的函數實現了兩個功能
一、對傳入的state初始值判斷類型,並嘗試從sessionStorage中讀取數據替換默認值
二、經過Proxy重置state的set邏輯,添加同步保存到sessionStorage的邏輯緩存
其實原本能夠經過Proxy重置get邏輯處理取值的問題,可是因爲vuex自己經過defineProperty函數重置了get邏輯,在這裏使用proxy覆蓋會有衝突,所以在初始化的時候直接讀取sessionStorage。session
同時也存在一些問題:
一、目前只處理了一級屬性,二級如下屬性沒處理,對於初始化會有誤差。對於這點處理層級也不宜過深,由於過深的結構設計原本就並不合理,兩層基本也足夠了。基本處理就是對於state的每一個key再去遍歷一遍,若是是object(非null非數組非空對象)就從新proxy一下
二、能夠嘗試打包成npm包,或者寫成Vuex的插件形式,方便使用
三、等等函數
~狀態很差,先寫到這,你們有興趣一塊兒來討論,清清腦子再來補充~
聯想到的一些點: 一、memory cache和disk cache?內存怎麼清理?js垃圾回收機制? 二、SessionStorage怎麼作到會話期緩存? 三、session機制怎麼回事? 四、http的無狀態?狀態保持?客戶端保持?服務端保持? 五、等等等等 發散開看看,一個地方真的能學到不少東西。。。