前言css
近期,用vue框架作了個後臺管理項目,涉及權限,參考網上資料,得此項目https://github.com/zhangxuexi...。
不知你們是否仍是各類mock工具來模擬數據,此項目,包含一個基於express,搭建的mock模擬服務,我的以爲,高大上了一點有木有!vue
啓動node
mock項目:webpack
cd mock npm install npm start 基於node.js的mock服務就啓動起來了。
項目目錄git
請求接口路由都在這個routes/index.js裏定義,接口返回的都是寫死的json數據。如需鏈接數據庫等操做請自行百度。這個項目不做重點介紹github
myProject項目:web
cd myProject npm install npm run dev
兩個項目分別啓動起來後,可用下面帳號登陸:
角色1:用戶名:123 密碼:a123456
角色2:用戶名:456 密碼:a123456vuex
router.js 權限路由
重點來了,直接上乾貨!數據庫
這部分是webpack的代碼分割,模塊可按需加載,也就是懶加載,具體知識可點擊連接進去查看。express
不授權限控制的通用路由可定義在這裏,直接在vue實例中注入便可。
export const asyncRoutes = [ { path: 'home', component: home, redirect: '/home/index', meta: {role: ['0', '1'], nav: false}, children: [ { path: '/home/index', name: '概覽', component: companyIndex, meta: { role: ['1'], nav: true } }, { path: '/home/index', name: '概覽', component: userIndex, meta: { role: ['0'], nav: true } }, { path: '/policy', name: '列表管理', component: policy, redirect: '/policy/list', meta: { role: ['0'], nav: true }, children: [ { path: 'list', name: '列表', component: userList, meta: { role: ['0'], nav: true } } ]}, { path: '/policy', name: '列表管理', component: policy, redirect: '/policy/company', meta: { role: ['1'], nav: true }, children: [ { path: '/policy/company', name: '列表', redirect: '/policy/company/list', component: policy, meta: { role: ['1'], nav: true }, children: [ { path: 'list', name: '列表', component: companyList, meta: { role: ['1'], nav: false } }, { path: 'detail/:policyNum', name: '列表詳情', component: detailCompany, meta: { role: ['1'], nav: false } }, { path: 'add', name: '添加', component: addCompany, meta: { role: ['1'], nav: false } } ]} ] } ] } ]
這部分是權限路由,以每一個路由記錄的元信息字段,定義權限。
meta:{role:['0'], nav:true}
role:表明這條路由記錄的所屬角色,nav:true表明要顯示在導航欄,例如一些列表路由,false:表明不顯示在導航欄,例如添加,查看路由。
router.beforeEach((to, from, next) => { // 第一步 先去vuex拉取用戶信息 let info = store.state.userInfo let infoLength = Object.keys(info).length === 0 // infoLength爲true 說明是第一次訪問系統或者刷新頁面,在這裏判斷路由'/login',防止進入死循環。未登陸,status爲1,跳到登陸頁面,已登陸,status爲0,繼續訪問頁面 if (infoLength && to.path !== '/login' && to.path !== '/forget') { store.dispatch('getUserInfo').then((response) => { if (response.status === '0') { store.dispatch('userLogin', response.data) // 將用戶基本信息存入vuex store.dispatch('permission', response.data.userType).then(() => { // 根據用戶角色,動態添加權限路由 router.addRoutes(store.state.navList) next({ ...to, replace: true }) } ) } else if (response.status === '1') { next('/login') } else if (response.status === '2') { // 刷新時登陸失效 next() // 刷新後 加載出原頁面再提示登陸失效,防止出現空白頁面 Message({ message: '登陸失效,請從新登陸', type: 'error', duration: 2000, showClose: true, customClass: 'my-el-message', onClose: function () { next('/login') } }) } }) } else { // infoLength爲false 說明是靜態點擊,不須要任何操做 next() } })
代碼註釋寫的很詳細了,這裏用了vuex,作狀態管理,仍是很方便的。
這段代碼流程:刷新或第一次訪問項目的時候,會請求這個接口,
,
若是接口返回正確數據,說明是已登陸,繼續跳轉路由
若是未返回正確數據,則跳回登陸路由。
接口返回正確數據後,根據權限,去篩選路由
vuex:permission詳情
import { asyncRoutes } from '@/router/index' import { getUserInfo } from '@/common/getUser' const actions = { userLogin: ({commit}, userData) => commit('userLogin', userData), /* 用戶信息存儲 */ permission: ({commit}, role) => { /* 根據權限信息加載權限路由 */ let routeArr = deepCopy(asyncRoutes) // 含有複雜數組對象,循環進行深拷貝 const b = filterAsyncRouter(routeArr, role) commit('navList', b) }, getUserInfo: ({commit}) => { // 檢驗是否登陸請求 return getUserInfo() } } // 根據權限 篩選路由 function filterAsyncRouter (asyncRouterMap, roles) { const accessedRouters = asyncRouterMap.filter(route => { if (route.meta.role.indexOf(roles) >= 0) { if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children, roles) } return true } return false }) return accessedRouters } function deepCopy (routeArr) { return routeArr.map((arr) => { arr = Object.assign({}, arr) return arr }) } export default actions
針對刷新時,vuex中數據丟失,這裏,沒有使用localstorge或者sessionstorge作緩存,主要考慮這兩種緩存方式的缺點均不符合公司業務要求,localstorge:手動清除才能消失,sessionstorge:只在本標籤頁有效。
不如直接來個接口,讓後端判斷登陸時效來的更安全。
好了,關於路由的就分析到這裏,你們理解了嗎?歡迎你們star哈
https://github.com/zhangxuexi...