vue-element-admin 项目代码学习 - 02 - vuex
前言
系列 vue-element-admin 项目代码学习,其他文章可参考:
vue-element-admin 项目代码学习 - 01 - main.js
话不多说,上代码
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
// set './app.js' => 'app'
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
项目中对vuex的数据使用模块化管理,在modules中按模块分别定义了,user(用户)、tagsView(标签)、settings(全局配置项)、permission(权限)、errorLog(错误日志)、app(全局状态模式),在对应的js文件中可以清晰的看到相应的字段和方法。
导入指定文件模块
const modulesFiles = require.context('./modules', true, /\.js$/)
webpack的api,通过执行require.context函数获取一个特定的上下文,主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块。
require.context函数接受三个参数
1.directory {String} -读取文件的路径
2.useSubdirectories {Boolean} -是否遍历文件的子目录
3.regExp {RegExp} -匹配文件的正则
require.context 返回一个函数,这个函数有三个属性
1.resolve {Function} -接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径
2.keys {Function} -返回匹配成功模块的名字组成的数组
3.id {String} -执行环境的id,返回的是一个字符串,主要用在module.hot.accept,应该是热加载?
这三个都是作为函数的属性(注意是作为函数的属性,函数也是对象,有对应的属性)
代码中通过keys方法,获取了名字组成的数组,通过正则替换,把文件名 xxx.js 换成 xxx, 然后使用reduce,遍历得到每个文件名为key,value为文件内容的 modules 对象,最后在vuex中引入。
modules/getter.js
对vuex中的state里的数据进行转换处理,就相当于 computed 计算属性一样。项目中可以看到他这里定义了之后再数据中取值不用再嵌套。
modules/user.js
用户token,name, roles 等都在该文件下处理,mutations中对定义的字段数据进行更变,在actions中异步定义 login 登录方法,拿到用户token,然后通过 getInfo 方法,传递token,拿到权限表,name等字段。 退出登录时调用 logout 方法。方法内部都使用promise处理异步。动态修改用户权限使用changeRoles 方法,重设token,权限表,动态路由等。
可以看到项目中的模块化做的很好,根据功能划分了不同的api接口,公共方法等,在自己的项目中值得借鉴。
modules/tagsView.js
tab标签上的数据在该文件下处理, 该页面定义了,visitedViews,cachedViews 两个标签数组,一个是普通的,一个用作缓存时的。并依据业务对数据定义新增、编辑、删除等方法。
modules/settings.js
全局配置项设置文件,该页面定义了,是否显示右侧页面设置按钮、tagsview、侧边栏徽标等。
modules/permission.js
路由表数据定义,页面中定义了用户路由表字段,定义了generateRoutes 方法通过传入权限,从router文件里定义的动态路由过滤出有当前权限的路由表。然后mutations修改数据。
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
if (roles.includes('admin')) {
accessedRoutes = asyncRoutes || []
} else {
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
modules/errorLog.js: 错误日志数据搜集
modules/app.js: 侧边栏状态,页面整体文字大小设置。配合cookie一起使用。
个人学习,可能理解有不足的地方,谢谢~