咱们在作后台系统的时候,常常会有比较多的功能页面,每一个页面或多或少都会有须要存储在vuex中的数据,通常状况下咱们会在state下定义不一样的object,可是当功能一多,所有字段和action、mutations都定义在一个文件里,不免会使文件变得很难维护。所有页面的路由都定义在一个路由文件里也会使文件代码变得比较多,后期维护麻烦。因此咱们应该将仓库和路由“模块化”,不一样功能定义不一样的模块文件,最后统一在index文件引入。javascript
router/index.js主要功能是:vue
// index.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// 定义常规路由
export const constantRoutes = [
{
path: '/redirect',
component: () => import('@/layout'),
hidden: true,
children: [
{
path: '/redirect/:path*',
component: resolve => void require(['@/views/redirect/index'], resolve)
}
]
},
{
path: '/',
redirect: '/login'
},
{
path: '/login',
name: 'Login',
component: resolve => void require(['@/views/login/index'], resolve),
hidden: true
},
{
path: '/register',
name: 'Register',
component: resolve => void require(['@/views/login/register'], resolve),
hidden: true
},
{
path: '/resetPsw',
name: 'ResetPsw',
component: resolve => void require(['@/views/login/resetPsw'], resolve),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
}
]
/** 权限路由 * 是动态的路由、须要根据权限加载的路由 */
const modulesFiles = require.context('./modules', true, /\.js$/)
const routesModules = []
// 自动引入modules目录下的全部模块
modulesFiles.keys().reduce((modules, modulePath) => {
const value = modulesFiles(modulePath)
routesModules.push(value.default)
}, {})
export const asyncRoutes = routesModules
/** 404路由 * 最终没法匹配到相应路由,重定向到404 * 异步加载路由时,在生成完异步路由准备挂载时,须要将重定向404的匹配规则定义在最后面,不然刷新会出错。 */
export const notFoundRoutes = [
{
path: '*',
redirect: '/404',
hidden: true,
meta: {
title: '404'
}
}
]
// 定义实例化路由的方法
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes // 挂载常规路由
})
// 实例化路由
const router = createRouter()
// 定义实重置路由的方法
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router
复制代码
和router模块同样,咱也须要给store模块建立一个文件夹,在里头存放定义文件java
该文件声明了vuex实例,同时批量引入modules下的store文件,也声明了vuex-persistedstate插件实例。git
关于persistedState的初始化,注意vuex中的参数不是所有都要持久化,你能够根据业务逻辑自行定义须要持久化的参数 github
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import createPersistedState from 'vuex-persistedstate'
Vue.use(Vuex)
// (建立了)一个包含了modules文件夹(包含子目录)下面的,全部文件名以 `.js` 结尾的、能被 require 请求到的文件的上下文。
const modulesFiles = require.context('./modules', true, /\.js$/)
// keys() 方法用于从modules建立一个包含modules里键值的可迭代对象。
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// 模块名,取文件名
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
// 获取键名为modulePath的文件内容
const value = modulesFiles(modulePath)
// 将文件中的默认导出模块 赋值给迭代对象modules
modules[moduleName] = value.default
// 返回迭代对象modules
return modules
// 默认值是空对象{}
}, {})
// 建立仓库实例
const store = new Vuex.Store({
modules,
getters,
// 使用持久化插件
plugins: [
// 存储vuex状态,使之刷新不丢失
createPersistedState({
// 这里我用的是localStorage,你也能够改为sessionStorage,cookie也行不过我没研究嘻嘻嘻
storage: window.localStorage,
reducer(val) {
return {
// 将要存储的state中的值放在这里
user: {
name: val.user.name
}
}
}
})
]
})
export default store
复制代码
那咱们就来看看咋使用,咱们能够写个userjs来试试,里头定义登陆登出的action,由于登陆登出可能不止一个地方会运用到,并且登陆登出可能会涉及到state里头好几个状态值的改变,因此我就把登陆登出的逻辑写在action里头,这样分发的时候也能够改变状态值:vue-router
import API from '@/assets/http/apiUrl'
import Request from '@/assets/http'
const user = {
state: {
token: '',
name: ''
},
mutations: {
SET_TOKEN: (state, data) => {
// 先初步定义token和username这两个值
state.token = data
localStorage.setItem('ADMIN_TOKEN', data)
},
SET_NAME: (state, data) => {
state.name = data
}
},
actions: {
// 登录
Login({ commit }, params) {
return new Promise((resolve, reject) => {
Request.httpRequest({
method: 'post',
url: API.Login,
params: params,
success: data => {
commit('SET_TOKEN', data.token)
resolve(data)
},
error: err => {
reject(err)
}
})
})
},
// 短信登陆,这里为了方便我就直接复用登陆的action了,正式项目中确定要调用另外的接口
LoginByVin({ dispatch, commit }, params) {
return dispatch('Login', params)
},
// 重置token和state值
ResetToken({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SEI_NAME', '')
localStorage.removeItem('ADMIN_TOKEN')
resolve()
})
},
// 登出
LogOut({ dispatch, commit }) {
return dispatch('ResetToken')
}
}
}
export default user
复制代码
新建以后不须要在index那里引入哦,由于咱们已经写了批量引入的逻辑啦~是否是很方便呢vuex
而后就是使用了,关于Login,在登录页面只须要分发action就行:api
params = {
'username': this.loginForm.user,
'password': this.loginForm.password
}
this.$store.dispatch('Login', params).then(() => {
this.loading = false
this.$router.push({ path: this.redirect || '/home' })
}).catch(() => {
this.loading = false
})
复制代码
具体代码逻辑能够下载项目来看一下下bash