国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

關于頁面刷新vuex數據消失問題解決方案

2019-11-19 16:11:23
字體:
來源:轉載
供稿:網友

VBox持續進行中,哀家苦啊,有沒有誰給個star。

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/lockrexport 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刷新的時候出現數據消失

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 广丰县| 佳木斯市| 京山县| 贵阳市| 临高县| 米泉市| 那曲县| 轮台县| 瑞安市| 易门县| 巴林右旗| 恩施市| 安岳县| 开化县| 威信县| 威远县| 井研县| 齐河县| 赣州市| 龙江县| 五河县| 伊金霍洛旗| 丹巴县| 阿鲁科尔沁旗| 阿巴嘎旗| 望都县| 博罗县| 静安区| 偃师市| 丹棱县| 会东县| 津市市| 南漳县| 双柏县| 宜章县| 都安| 苍梧县| 林周县| 托克托县| 三江| 当雄县|