您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何解決頁面刷新vuex數據消失的問題”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“如何解決頁面刷新vuex數據消失的問題”這篇文章吧。
vuex是vue用于數據存儲的,和redux充當同樣的角色。
最近在VBox開發的時候遇到的問題,頁面刷新或者關閉瀏覽器再次打開的時候數據歸零。這是頭疼的問題。
網上搜,大家的方案都是把數據轉移到 localStorage或者其他持久化存儲(例如indexDB)。
這倒是可以,我在設計之初因為匆忙,沒有考慮周全,這下好,然不成每個 mutation都去存一下。
這個弄的我很不開心,周六在公司,本來就困的要死,又想不到合理的解決方案,昏昏沉沉睡著了。
醒了后,最初想采用 柯里化和高階函數來解決這個問題,很可惜,沒有正解。
最小化修改,又不想動現有代碼,代理二字最為不過。記得上次我寫IBook之初,也用Proxy來攔截修改,同時存數據到磁盤文件。
沒錯方案就是 ES6的Proxy,嘗試之后,確實是可以的。
源碼地址:https://github.com/xiangwenhu/vbox/tree/master/src/utils
這里有兩個問題
1. 初始值的問題。
2. 我要可以配置哪些字段需要持久化,store里面的數據,不代表我都需要持久化。
首先解決是 localStorage存儲的問題,因為需要轉換字符串,簡單封裝一個 LStorage.js,當然你也可以用 https://github.com/tsironis/lockr , https://github.com/nbubna/store 或者你喜歡的,小輪子我就自己寫了。
const ls = window.localStorage // https://github.com/tsironis/lockr export default { getItem(key) { try { return JSON.parse(ls.getItem(key)) } catch (err) { return null } }, setItem(key, val) { ls.setItem(key, JSON.stringify(val)) }, clear() { ls.clear() }, keys() { return ls.keys() }, removeItem(key) { ls.removeItem(key) } }
其次就是代理的簡單封裝,LSproxy.js
這個版本還是有問題的,現在只能代理二級屬性,對現在的我而言已經是夠用了的。
createHanlder 創建二級屬性的代理
copy 復制對象,當然你可以寫更加兼容優雅的方法
proxy 創建state的代理
import LStorage from './LStorage' /** * 代理二級屬性 * @param {*} lsKey 存在localStorage的key * @param {*} pk 一級屬性的key */ function createHanlder(lsKey, pk) { return { set: function (target, key, value, receiver) { let item = LStorage.getItem(lsKey) if (item && item[pk]) { item[pk][key] = value LStorage.setItem(lsKey, item) } return Reflect.set(target, key, value, receiver) } } } /** * 僅僅存需要存放的數據 * @param {*} source * @param {*} keys */ function copy(source, keys = []) { if (!source) { return source } let d = Object.create(null) keys.forEach(k => { d[k] = source[k] }) return d } /** * 代理state * @param {*} initState 初始化的值 * @param {*} lsKey localStorage的key * @param {*} keys 需要存儲的鍵 */ const proxy = function (initState, lsKey, keys = []) { let ks = keys, obj = Object.assign({}, initState, LStorage.getItem(lsKey)) // 代理二級屬性 keys.forEach(k => { obj[k] = new Proxy(obj[k], createHanlder(lsKey, k)) }) // 存入合并的值 LStorage.setItem(lsKey, copy(obj, keys)) return new Proxy(obj, { set: function (target, key, value, receiver) { ks.indexOf(key) >= 0 && LStorage.setItem(lsKey, copy(target, keys)) return Reflect.set(target, key, value, receiver) } }) } export { proxy }
調用這邊,基本就沒有什么變化, 就多了一句 state = proxy(state, 'playing', ['list'])
import { proxy } from '../utils/LSProxy' let state = { list: [], current: null } state = proxy(state, 'playing', ['list']) const mutations = { /** * 添加歌曲 * @param {*} state * @param {*} song 歌曲信息 */ addSong(state, song) { let index = state.list.findIndex(s => s.songmid === song.songmid) if (index < 0) { state.list.push(song) } }, /** * 添加歌曲 * @param {*} state 內置 * @param {*} songs 歌曲列表 */ addSongs(state, songs) { let index = -1 songs.forEach(song => { index = state.list.findIndex(s => s.songmid === song.songmid) if (index < 0) { state.list.push(song) } }) }, /** * 刪除歌曲 * @param {*} state * @param {*} songmid 歌曲媒體id */ removeSong(state, songmid) { let index = state.list.findIndex(s => s.songmid === songmid) index >= 0 && state.list.splice(index, 1) }, /** * 批量刪除歌曲 * @param {*} state * @param {*} songmids 歌曲媒體列表 */ removeSongs(state, songmids = []) { let index = -1 songmids.forEach(songmid => { index = state.list.findIndex(s => s.songmid === songmid) index >= 0 && state.list.splice(index, 1) }) }, /** * 播放下一首, * @param {*} state * @param {*} song 為空 */ next(state, song) { // 如果song不為空,表示是插放,(前提是已經添加到playing) if (song) { let index = state.list.findIndex(s => s.songmid === song.songmid) if (index >= 0) { state.current = state.list[index] return } return } // 如果current為空,表示沒有播放的歌曲 if (!state.current && state.list && state.list.length > 0) { state.current = state.list[0] return } // 如果不是插放,并且current不為空 if (!song && state.current) { // 播放的歌曲是不是在當前的列表 let index = state.list.findIndex(s => s.songmid === state.current.songmid) // 如果在歌曲列表里面,接著播放下首 if (index >= 0) { state.current = (index === state.list.length - 1 ? state.list[0] : state.list[index + 1]) } else { state.current = state.list[0] } } } } export default { namespaced: true, state, mutations }
這種方案的缺點也是很明顯的,
1. 代碼只能代理二級,對我一般情況應該是夠用了,扁平化state
2. 代理二級屬性和數組,要是屬性平凡修改的時候,代理是會重復觸發的,比如,添加30首歌曲的時候,是發生了30次存儲。 當然我覺得也是有方案可以優化的。
優點我覺得是,
1. state的數據與localStorage的同步過程分離開
2. 對現有代碼的注入是相當少的。
當然我上面代碼本身也還是存在問題的
1. 二級監聽不能在proxy執行的時候返回,因為如果屬性默認值為null/undefined,或者初始化就沒有設置默認值,是不會被監聽到的,應該是放到一級屬性監聽里面, 進行一個判斷。
以上是“如何解決頁面刷新vuex數據消失的問題”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。