前情回顧:
vue-element-admin項目學習筆記(1)安裝、配置、啟動項目
vue-element-admin項目學習筆記(2)main.js
文件分析
vue-element-admin項目學習筆記(3)路由分析一:靜態(tài)路由
vue-element-admin項目學習筆記(4)路由分析二:動態(tài)路由及permission.js
vue-element-admin項目學習筆記(5)路由分析三:動態(tài)路由匹配邏輯
關于什么是vuex?和理論部分,本篇不做討論,假設前提是,你已經學習和掌握了vue基礎的小伙伴。
vuex的核心有四個部分:
- state :狀態(tài),也可以理解為變量
- mutation :操作狀態(tài)的地方
- action :操作狀態(tài)之前需要處理異步或業(yè)務邏輯
- getter :對狀態(tài)進行包裝,理解為計算屬性computed
也可以參考我之前發(fā)過的一篇:
VueX使用簡明筆記
本篇還是圍繞Vue-Element-Admin項目,針對Vuex狀態(tài)管理的角度進行簡單分析。
這部分也是非常重要的,關乎項目內部業(yè)務邏輯、交互邏輯
1、Vue-Element-Admin項目中vuex倉庫概況
Vue-Element-Admin項目的store倉庫位置在項目目錄/src/store
這個路徑下。
結構如下:
-
modules目錄
內主要存放的一些自定義的子倉庫模塊,你自己寫的,最好也按照規(guī)范存到這里 -
./modules/app.js
存儲和操作cookie、語言切換、默認尺寸等狀態(tài),理解為全局變量也行 -
./modules/errLog.js
定義和操作項目錯誤日志狀態(tài) -
./modules/permission.js
權限狀態(tài)的定義和操作,這個在動態(tài)路由計算那篇中,已經詳細聊過了 -
./modules/settings.js
系統(tǒng)設置狀態(tài)的定義和操作,包括主題等 -
./modules/tagsView.js
小頁簽狀態(tài)的定義和操作,下圖就是: -
./modules/user.js
重要,用戶的狀態(tài)、狀態(tài)操作,都在這,比如登錄、登出這些邏輯,以及后面會說到的后端校驗接口,也是通過它在調用并修改狀態(tài) -
./getters.js
對全局需要的一些狀態(tài)(變量),比如用戶信息、動態(tài)路由規(guī)則、設置等進行集中抽取并暴露。 -
./index.js
是倉庫入庫,主要完成的工作,是對子倉庫模塊的引入和注冊
2、store入口文件index.js
一步步看注釋:
// 引入vue
import Vue from 'vue'
// 引入vuex
import Vuex from 'vuex'
// 引入getters 理解為全局變量
import getters from './getters'
// 使用vuex,因為本質上是插件
Vue.use(Vuex)
// 在modules目錄下讀取所有模塊文件名
const modulesFiles = require.context('./modules', true, /\.js$/)
// 過濾匹配模塊名:值 返回modules
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
3、權限狀態(tài)控制permission.js
一步步看注釋:
// 導入動態(tài)、靜態(tài)路由規(guī)則
import { asyncRoutes, constantRoutes } from '@/router'
// 具體路由規(guī)則與用戶roles匹配的工具函數,被filterAsyncRoutes調用
// 返回布爾值
function hasPermission(roles, route) {
// 規(guī)則有元信息 且 元信息 有roles項
if (route.meta && route.meta.roles) {
// 開始比對,role在不在route.meta.roles中,返回比對結果
return roles.some(role => route.meta.roles.includes(role))
} else {
//沒有元信息,可以返回真,說明沒有配置權限,可以訪問
return true
}
}
// 遍歷路由規(guī)則與用戶roles匹配的工具函數
export function filterAsyncRoutes(routes, roles) {
const res = []
// 遍歷傳過來的所有動態(tài)路由規(guī)則進行遍歷
routes.forEach(route => {
// tmp 每一個規(guī)則
const tmp = { ...route }
// 調用hasPermission方法(布爾值),進行匹配
if (hasPermission(roles, tmp)) {
// 子級路由遞歸計算
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res
}
// 兩個狀態(tài)、數組routes、addRoutes
// routes 當前用戶所有路由
// addRoutes 當前用戶動態(tài)路由。權限計算出來的
// 通過瀏覽器vue插件可以觀察看到
const state = {
routes: [],
addRoutes: []
}
// mutations操作state
// 給這兩個數組賦值
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes)
}
}
// actions操作異步
// generateRoutes方法,計算生成權限動態(tài)路由
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
// 定義一個臨時變量
let accessedRoutes
// 當前用戶的roles中是否包含admin
if (roles.includes('admin')) {
// 包含的話,就把所有動態(tài)路由規(guī)則給它,asyncRoutes是所有動態(tài)路由,導入的
// admin用戶不用計算
accessedRoutes = asyncRoutes || []
} else {
// 否則在所有動態(tài)路由規(guī)則中進行過濾匹配
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
}
// 提交修改數組
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
4、用戶狀態(tài)控制user.js
// 引入src/api下的user接口,登錄login, 退出登錄logout, 獲取用戶信息getInfo
import { login, logout, getInfo } from '@/api/user'
// 引入src/utils/auth下的三個方法:獲取getToken, 設置setToken, 刪除removeToken
import { getToken, setToken, removeToken } from '@/utils/auth'
// 引入路由以及resetRouter重置路由方法,重置是因為切換用戶/切換登錄,需要重置
import router, { resetRouter } from '@/router'
// 定義用戶信息(數據、狀態(tài))
const state = {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: []
}
// mutations是改變狀態(tài)的唯一途徑
// 改變用戶信息的一些操作
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
}
}
// 異步操作
const actions = {
// 用戶登錄
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)
})
})
},
// get user info
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)
})
})
},
// user logout
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
// 先調了退出登錄的接口logout,傳入token,后端作廢處理后返回
logout(state.token).then(() => {
commit('SET_TOKEN', '')//清理倉庫中的token
commit('SET_ROLES', [])//清理倉庫中的權限
removeToken()//移除cookie中的token
resetRouter()//重置路由,清理為當前用戶計算的動態(tài)路由規(guī)則
// 清空tagsView(就是打開頁面的小標簽)
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
})
})
},
// remove token
resetToken({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
})
},
// dynamically modify permissions
async changeRoles({ commit, dispatch }, role) {
const token = role + '-token'
commit('SET_TOKEN', token)
setToken(token)
const { roles } = await dispatch('getInfo')
resetRouter()
// generate accessible routes map based on roles
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// reset visited views and cached views
dispatch('tagsView/delAllViews', null, { root: true })
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
5、系統(tǒng)錯誤日志狀態(tài)控制errLog.js
一步步看注釋:
// 定義狀態(tài),logs數組
const state = {
logs: []
}
// 定義兩個改變狀態(tài)的方法
// ADD_ERROR_LOG 添加日志
// CLEAR_ERROR_LOG 清除
const mutations = {
ADD_ERROR_LOG: (state, log) => {
state.logs.push(log)
},
CLEAR_ERROR_LOG: (state) => {
state.logs.splice(0)
}
}
// 定義兩個action方法,同上,commit到mutation中執(zhí)行改變
const actions = {
addErrorLog({ commit }, log) {
commit('ADD_ERROR_LOG', log)
},
clearErrorLog({ commit }) {
commit('CLEAR_ERROR_LOG')
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
為什么要單獨說一下errLog.js,因為在實際工作中,我們可以在這里,拿到錯誤日志,并且寫入數據庫或者文件文章來源:http://www.zghlxwxcb.cn/news/detail-485990.html
其他模塊就不一一拿出來說了,后面用到,會說明文章來源地址http://www.zghlxwxcb.cn/news/detail-485990.html
到了這里,關于Vue-Element-Admin項目學習筆記(6)Vuex狀態(tài)管理的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!