以前我寫了一篇用ES6 Proxy方案解決數據同步的文章 頁面刷新vuex數據消失問題解決方案.html
今天和同事溝通這個vuex數據還原問題,我說個人方法很奇異。聊着聊着,同事咋不用 store.subscribe , 當時還有點以爲不可能,仔細再去看vuex官方文檔。vue
這個還真的是可行,但固然也是存在不方便的地方的。git
此方案如今已經應用我基於vue開發的音樂web app VBOX 上,歡迎你們給star.github
基本方案和步驟以下web
1. 簡單的按照鍵複製對象vuex
2. localStorage存儲的封裝app
3. vuex插件編寫插件
4. localStorage的數據還原和初始化 Vuex.Storehtm
第一:簡單的按照鍵複製對象對象
/** * 數據簡單複製 * @param {*} source * @param {*} keys */ const copy = function (source, keys = []) { if (!source) { return source } let d = Object.create(null) keys.forEach(k => { d[k] = source[k] }) return d } export { copy }
第二:localStorage的簡單封裝
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) } }
第三:vuex插件
主要是一個lsKey,存到localStorage的key,
另一個是 mutation白名單,白名單內的觸發不會觸發數據同步
實際上這裏是存在必定問題的,這裏適用模塊後的store
(1) 沒法快速有效便捷的定位何時該觸發同步
import ls from '../utils/LStorage' import { copy } from '../utils/utils' export const createLSPlugin = function (lsKey, mappings, whitelist = []) { let k = lsKey || 'lsKey' return store => { store.subscribe((mutation, state) => { if (whitelist.findIndex(m => m === mutation.type) < 0) { let cd = Object.create(null) Object.keys(state).forEach(k => { if (mappings[k]) { cd[k] = copy(state[k], mappings[k]) } }) ls.setItem(k, cd) } }) } }
第四:初始化Vuex.Store
主要是從localStore裏面還原數據合併到state裏面,若是state沒有分模塊仍是比較簡單的。
import Vue from 'vue' import Vuex from 'vuex' import playing from './playing' import player from './player' import searchHistory from './searchHistory' import { createLSPlugin } from '../plugin/syncls' import ls from '../utils/LStorage' const LS_KEY = 'vbox' const lsData = ls.getItem(LS_KEY) let mapping = { playing: ['list', 'current'], player: ['mode'], searchHistory: ['list'] } let mWhiteList = ['player/timeUpdate', 'player/setState'] if (lsData) { let { playing: ls_playing, player: ls_player, searchHistory: ls_searchHistory } = lsData Object.assign(playing, { state: ls_playing }) Object.assign(player, { state: ls_player }) Object.assign(searchHistory, { state: ls_searchHistory }) } Vue.use(Vuex) const plugin = createLSPlugin(LS_KEY, mapping, mWhiteList) const store = new Vuex.Store({ modules: { playing, player, searchHistory }, plugins: [plugin] }) export default store
優勢
1. 代碼簡單,對代碼改動不大
2. 對原始的state沒有額外干預
缺點
1. 觸發存儲條件很差控制
2. 存儲限制實現會相對複雜