一、前置知识
1. vuex的plugins选项
- 该选项接收一个数组,数组每一项是一个函数(也就是一个插件)
- 项目初始化后,数组的每一项,会依次执行一次,且接收store
import { createStore } from 'vuex'
export default createStore({
// ......
plugins: [fn1, fn2] // store初始化后,fn1和fn2会依次执行
})
function fn1(store){
console.log(store) // 函数会接收store
}
function fn2(store) {
console.log(store)
}
2. store.subscribe方法监听mutation
- 该方法接收一个回调函数作为参数
- 只要mutation中的方法执行,就会执行该回调函数
- 该回调函数会接收两个参数,一个是当前执行mutation,一个是state
import { createStore } from 'vuex'
import modules1 from './modules/modules1'
export default createStore({
// ......
mutations: {
ADDCOUNT: (state,data) => {
state.count = data
}
},
modules: {
modules1
},
plugins: [fn1]
})
function fn1(store){
store.subscribe((mutations,state) => {
console.log(mutations, state) // 回调函数会接收mutation和state
})
}
3. store.replaceState替换旧的state
- 由于state是响应式数据,不能直接赋值,所以使用replaceState方法修改state
store.replaceState(newState)
二、实现简易vuex持久化插件
思路:
- 在插件中监听mutation执行,mutation执行时设置缓存
- 刷新时,将缓存中的数据替换到state中
代码:
// 使用
import { createStore } from 'vuex'
import modules1 from './modules/modules1'
export default createStore({
modules: {
modules1
},
plugins: [ persistencePlugin ]
})
// 插件函数
function persistencePlugin(store) {
// 初始化(刷新)时,取缓存,设置state
const storage = JSON.parse(sessionStorage.getItem('state'))
if (storage) {
store.replaceState(storage)
}
// 监听mutation执行,存缓存
store.subscribe((mutation, state) => {
sessionStorage.setItem('state', JSON.stringify(state))
})
}
三、自定义vuex持久化内容
支持定义:
- 需要持久化的内容
- 缓存key名称
- session还是local缓存
插件代码:
/*
* watch:需要监听的数据,默认监听全部
* keyName:存储缓存的key名称,默认'vuex'
* storage:缓存类型,默认sessionStorage
*/
export function persistencePlugin(customConfig) {
let {
watch = '*',
keyName = 'vuex',
storage = 'sessionStorage'
} = customConfig
// 返回一个函数
return function (store) {
const data = JSON.parse(window[storage].getItem(keyName))
if (data) {
if (watch == '*') {
store.replaceState(data) // 监听全部,直接替换state
} else {
// 只修改部分state
setObject(store.state, watch, data)
}
}
// 监听state变化,存缓存
store.subscribe((mutation, state) => {
if (watch == '*') {
// watch监听全部,全部存缓存,使用自定义的keyName
window[storage].setItem(keyName, JSON.stringify(state))
} else {
// watch监听部分,部分存缓存
window[storage].setItem(
keyName,
JSON.stringify(parseObject(store.state, watch))
)
}
})
}
}
// 解析对象的值,key是a.b.c 这样的格式
function parseObject(obj, keyString) {
if (!keyString) return
const keys = keyString.split('.')
return keys.reduce((obj, key) => obj[key], obj)
}
// 设置对象的值,key是a.b.c格式时候
function setObject(obj, keyString, newDate) {
if (!keyString) return
const keys = keyString.split('.')
const lastIndex = keys.length - 1
keys.forEach((key, index) => {
if (index === lastIndex) {
// 最后一个索引,给对象赋值
obj[key] = newDate
} else {
// 不是最后一个所有,给obj重新赋值
obj = obj[key]
}
})
}
使用:
import { createStore } from 'vuex'
import modules1 from './modules/modules1'
export default createStore({
modules: {
modules1
},
plugins: [
persistencePlugin({
watch: 'modules1.modulesCount', // 持久化模块modules1中modulesCount的值
keyName: 'modulesCount', // 存储的keyname
storage: 'localStorage' // 使用本地存储
})
]
})
效果:
若还需要其他自定义功能,可自行修改