以前的项目使用了modules做了store的结构调整,现在大多数项目也是这种结构。
├── mutation-types.js
├── module
├── actions
│ └── index.js
├── mutations
│ └── index.js
├── state
│ └── index.js
└── store
└── index.js但是随着项目越来越大,用起来觉得确实有点别扭了,(当你觉得别扭的时候,只能表明你的代码还有很大的优化空间)这可能就是所谓的码感,比如引入module的时候,每个module都要导入一遍,比如存储storage的时候,都是set,get却要重复使用,而且都放在mutations里面看上去太乱了,等等.....这些都是优化的点。
说干就干,程序员的脾气就是这样
一. modules的引入
以前我们的代码是这样
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
import check from "./module/check.js"
import maintain from "./module/maintain"
import user from "./module/user.js"
import machineStatus from "./module/machineStatus.js"
const store = new Vuex.Store({
getters: {
userInfo:state=>state.user.userInfo,
loginInfo:state=>state.user.loginInfo,
UserEId:state=>state.user.UserEId
},
modules:{
check,
user,
maintain,
machineStatus
}
})
export default store试想一下,如果有多个modules,我们岂不是得引到猴年马月......,可不可以用一个工具帮我们自动引入module文件下的所有js文件呢?emmm,当然可以
require.context(路径,是否包含子目录,文件名格式)获取指定目录下的文件context(fileName)获取指定文件名的文件
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const context = require.context('./module', true, /\.js$/);
console.log(context.keys())
let modules={}
context.keys().forEach((fileName)=>{
let key=fileName.replace(/(^\.\/)|(\.js$)/ig,"")
modules[key]=context(fileName).default
})
const store = new Vuex.Store({
getters: {
userInfo:state=>state.user.userInfo,
loginInfo:state=>state.user.loginInfo,
UserEId:state=>state.user.UserEId
},
modules
})
export default store妈呀,像变魔术一样,也太简洁了。
二. 制定持久化plugin
最开始的想法是通过switch来判断每次mutation的type,然后去存储,如果payload为空表示要从本地删除存储。
// import store from "./store"
import storage from "@/util/storage"
import hUtils from "@/util"
//统一管理localStorage,只是监听不是拦截操作
const storePlugin=()=>store=>{
store.subscribe((mutation,state)=>{
let {type,payload}=mutation;
let finalType
if(type.indexOf("/")>=0){
finalType=type.split("/")[1]
}
else{
finalType=type
}
switch(finalType){
case "SET_USEREID":
storage.set("UserEId", payload);
if (!payload){
storage.remove("UserEId")
};
break;
case "SET_LOGININFO":
storage.set("loginInfo", payload);
if (hUtils.isEmptyObj(payload)){
storage.remove("loginInfo")
};
break;
case "SET_USERINFO":
storage.set("userInfo", payload)
if (hUtils.isEmptyObj(payload)) {
storage.remove("userInfo")
};
break;
case "SET_CURRENTMACHINE":
storage.set("currentMachine",payload);
break;
case "SET_CURRENTMACHINEINDEX":
storage.set("currentMachineIndex",payload);
break;
default:"";break;
}
})
}
export default storePlugin但这种写法也有点累赘,后来参考了一篇博客,可以将它做成store中的插件,通过plugins这个参数来调用。并对匹配进行了优化,因为每个switch之后的操作都一样。
首先写一个工具函数判断是否为空,依次判断是否去删除本地存储
isEmpty.js
"",null,undefined,[],{}都表示为空,把0排除掉
isEmpty(value){
if(!value&&value!==0){
return true
}
else{
if(Object.prototype.toString.call(value)==="[object Array]"){
return value.length===0
}
if(Object.prototype.toString.call(value)==="[object Object]"){
return Object.keys(value).length === 0
}
}
return false
}改造后的plugin插件
import storage from "@/util/storage"
import hUtils from "@/util"
//统一管理localStorage,只是监听不是拦截操作
const storePlugin=()=>store=>{
store.subscribe((mutation,state)=>{
const storageObj={
["SET_USEREID"]:"UserEId",
["SET_LOGININFO"]:"loginInfo",
["SET_USERINFO"]:"userInfo",
["SET_CURRENTMACHINE"]:"currentMachine",
["SET_CURRENTMACHINEINDEX"]:"currentMachineIndex"
}//格式为mutation的键值和state的键值
let {type,payload}=mutation;
let finalType
if(type.indexOf("/")>=0){
finalType=type.split("/")[1]
}
else{
finalType=type
}
//将匹配到的值存储到storage中
if(Object.keys(storageObj).includes(finalType)){
console.log(finalType)
storage.set(storageObj[finalType],payload)
if(hUtils.isEmpty(payload)){
storage.remove(storageObj[finalType])
}
}
})
}
export default storePlugin在store中调用
const store = new Vuex.Store({
plugins:[MyPlugin()],
getters: {
userInfo:state=>state.user.userInfo,
loginInfo:state=>state.user.loginInfo,
UserEId:state=>state.user.UserEId
},
modules:{
check,
user,
maintain,
machineStatus
}
})后续优化,实现state从缓存中自动化获取
参考博客