对vue-element-admin后台开源框架的解读—vuex篇
文件夹示意
1.vuex核心–index.js
项目代码
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
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
解析1
批量引入vuex module从modules文件夹(对于模块特别多的vuex非常方便)不需要一个一个去import.
const modulesFiles = require.context(’./modules’, true, /.js$/)
Webpack API ----- require.context() 函数来创建自己的 context。
可以给这个函数传入三个参数:
- 一个要搜索的目录
- 一个标记表示是否还搜索其子目录
- 一个匹配文件的正则表达式。
示例
require.context('../', true, /\.stories\.js$/);
// (创建出)一个 context,其中所有文件都来自父文件夹及其所有子级文件夹,request 以 `.stories.js` 结尾。
require.context 知识点来源
解析2
对批量引入的模块通过数组的reduce方法让所有摸块组成一个大对象
把每一个js模块文件格式化为模块名 ./app.js’ => ‘app’
通过modulesFiles(modulePath)获取每个模块的内容
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^./(.*).\w+$/, ‘$1’)
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
js中的reduce()函数讲解
解析3
将vuex模块和getters注入store,并导出
const store = new Vuex.Store({
modules,
getters
})
2.vuex的计算属性–getters.js
将getters单独创建一个模块,配合 mapGetters 辅助函数可以很方便的获取vuex中的一些简单数据
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token,
......
}
export default getters
mapGetters 辅助函数获取数据
在组件中直接获取token
computed: {
...mapGetters(['token'])
}
3.vuex模块—登录,获取用户信息,登出模块–user.js
import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'
import router, { resetRouter } from '@/router'
const state = {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: []
}
// 注册所有的mutation方法
const mutations = {
//将函数赋值给一个变量
SET_TOKEN: (state, token) => {
state.token = token
},
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
}
//注册所有的action方法
const actions = {
// 登录
// 将commit 从 context 中结构出来
// Promise封装的组合式action
login({ commit }, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => {
const { data } = response
commit('SET_TOKEN', data.token)
setToken(data.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息
// 将commit,state从 context 中结构出来
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const { data } = response
if (!data) {
reject('Verification failed, please Login again.')
}
const { roles, name, avatar, introduction } = data
// roles must be a non-empty array
if (!roles || roles.length <= 0) {
reject('getInfo: roles must be a non-null array!')
}
commit('SET_ROLES', roles)
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
commit('SET_INTRODUCTION', introduction)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
// 登出
// 将commit, state, dispatch 从 context 中结构出来
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
})
})
},
// 清除token
resetToken({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
})
},
// 动态地修改权限
// async,await封装的组合式action
async changeRoles({ commit, dispatch }, role) {
const token = role + '-token'
commit('SET_TOKEN', token)
setToken(token)
const { roles } = await dispatch('getInfo')
resetRouter()
// 生成基于角色的可访问路由
// 需要分发其他模板的action或者提交其他模板的mutation的时候,需要加上{ root: true }
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// 动态添加可访问的路由
router.addRoutes(accessRoutes)
// 重置已访问视图和缓存视图
dispatch('tagsView/delAllViews', null, { root: true })
}
}
export default {
//添加 namespaced: true 的方式使其成为带命名空间的模块
namespaced: true,
state,
mutations,
actions
}