简单记录一下使用vue-element-admin
后台项目我采用的是vue-element-admin后台模板,我们下载下来做下改造。
1.关闭自带的mock
1-1 去除main.js
1 // if (process.env.NODE_ENV === 'production') { 2 // const { mockXHR } = require('../mock') 3 // mockXHR() 4 // }
1-2 vue.config.js加入
1 devServer: { 2 port: 5001, 3 open: true, 4 overlay: { 5 warnings: false, 6 errors: true 7 }, 8 proxy: { 9 '/': { 10 target: `xxx.com`,//要代理的地址 11 changeOrigin: true, 12 pathRewrite: { 13 '^/': ''//代理后的地址 14 } 15 } 16 }, 17 after: require('./mock/mock-server.js') 18 }
使用的话,正常使用比如 '/getList'
2.路由修改
1 import Vue from 'vue' 2 import Router from 'vue-router' 3 4 Vue.use(Router) 5 6 /* Layout */ 7 import Layout from '@/layout' 8 //固定的路由 9 export const constantRoutes = [ 10 { 11 path: '/redirect', 12 component: Layout, 13 hidden: true, 14 children: [ 15 { 16 path: '/redirect/:path(.*)', 17 component: () => import('@/views/redirect/index') 18 } 19 ] 20 }, 21 { 22 path: '/login', 23 component: () => import('@/views/login/index'), 24 hidden: true 25 }, 26 { 27 path: '/auth-redirect', 28 component: () => import('@/views/login/auth-redirect'), 29 hidden: true 30 }, 31 { 32 path: '/404', 33 component: () => import('@/views/error-page/404'), 34 hidden: true 35 }, 36 { 37 path: '/401', 38 component: () => import('@/views/error-page/401'), 39 hidden: true 40 }, 41 { 42 path: '/', 43 component: Layout, 44 redirect: '/dashboard', 45 children: [ 46 { 47 path: 'dashboard', 48 component: () => import('@/views/dashboard/index'), 49 name: 'Dashboard', 50 meta: { title: 'Dashboard', icon: 'dashboard', affix: true } 51 } 52 ] 53 } 54 ] 55 56 //动态路由不确定 57 export const asyncRoutes = [ 58 { 59 path:'/data', 60 component:Layout, 61 redirect:'/data/create', 62 meta:{title:'数据管理',icon:'documentation',roles:['admin','editor']}, 63 children:[ 64 { 65 path:'/data/create', 66 component:()=>import('@/views/data/create'), 67 meta: { title: '添加数据', icon: 'edit', roles: ['admin'] } 68 }, 69 { 70 path:'/data/edit', 71 component:()=>import('@/views/data/edit'), 72 hidden:true,//隐藏不在侧边栏显示 73 meta: { title: '编辑数据', icon: 'edit', roles: ['admin'],activeMenu:'/data/list' } 74 //activeMenu当路由为'/data/edit',侧边栏高亮对应'/data/list' 75 }, 76 { 77 path:'/data/list', 78 component:()=>import('@/views/data/list'), 79 meta: { title: '数据列表', icon: 'list', roles: ['editor'] } 80 } 81 ] 82 }, 83 //都匹配不到跳转404页面 84 { path: '*', redirect: '/404', hidden: true } 85 ] 86 87 const createRouter = () => new Router({ 88 // mode: 'history', // require service support 89 //切换路由滚到头部 90 scrollBehavior: () => ({ y: 0 }), 91 routes: constantRoutes 92 }) 93 94 const router = createRouter() 95 export function resetRouter() { 96 const newRouter = createRouter() 97 router.matcher = newRouter.matcher // reset router 98 } 99 100 export default router
3.权限判断
首先判断是否存在token:
没有token判断要去的页面是否需要token,不需要直接跳转,需要跳转登录页面并且带上要去的页面。
有token的时候如果要去登录页面,直接跳转主页面。不是登录页面的话,在判断是否存在用户信息,通过用户信息生成动态路由
1 import router from './router' 2 import store from './store' 3 import { Message } from 'element-ui' 4 import NProgress from 'nprogress' // progress bar 5 import 'nprogress/nprogress.css' // progress bar style 6 import { getToken } from '@/utils/auth' // get token from cookie 7 import getPageTitle from '@/utils/get-page-title' 8 9 NProgress.configure({ showSpinner: false }) 10 //白名单不需要token 11 const whiteList = ['/login', '/auth-redirect'] 12 13 router.beforeEach(async(to, from, next) => { 14 NProgress.start() 15 //修改顶部名字 16 document.title = getPageTitle(to.meta.title) 17 //获取token 18 const hasToken = getToken() 19 20 if (hasToken) { 21 if (to.path === '/login') { 22 //如果有token且要去的页面是登录页面,直接跳到主页面 23 next({ path: '/' }) 24 NProgress.done() 25 } else { 26 const hasRoles = store.getters.roles && store.getters.roles.length > 0 27 //判断是否拥有用户信息 28 if (hasRoles) { 29 next() 30 } else { 31 try { 32 //获取用户信息 33 const { roles } = await store.dispatch('user/getInfo') 34 //根据用户动态生成路由 35 const accessRoutes = await store.dispatch('permission/generateRoutes', roles) 36 router.addRoutes(accessRoutes) 37 next({ ...to, replace: true }) 38 } catch (error) { 39 await store.dispatch('user/resetToken') 40 Message.error(error || 'Has Error') 41 next(`/login?redirect=${to.path}`) 42 NProgress.done() 43 } 44 } 45 } 46 } else { 47 //在白名单直接跳转 48 if (whiteList.indexOf(to.path) !== -1) { 49 next() 50 } else { 51 //跳转到登录页面,并记录要去的路由 52 next(`/login?redirect=${to.path}`) 53 NProgress.done() 54 } 55 } 56 }) 57 58 router.afterEach(() => { 59 NProgress.done() 60 })
前面说没有token前往登录页面,现在分析登录页面。
1 watch: { 2 //监听路由变化获取路由参数,登录后需要跳转的页面和参数 3 $route: { 4 handler: function(route) { 5 const query = route.query 6 if (query) { 7 this.redirect = query.redirect 8 this.otherQuery = this.getOtherQuery(query) 9 } 10 }, 11 immediate: true 12 } 13 },
其中getOtherQuery为页面所带参数
1 getOtherQuery(query) { 2 return Object.keys(query).reduce((acc, cur) => { 3 if (cur !== 'redirect') { 4 acc[cur] = query[cur] 5 } 6 return acc 7 }, {}) 8 }
1 this.$store.dispatch('user/login', this.loginForm) 2 .then(() => { 3 //登录成功跳转到输入路由,携带参数 4 this.$router.push({ path: this.redirect || '/', query: this.otherQuery }) 5 this.loading = false 6 }) 7 .catch(() => { 8 this.loading = false 9 })
这里登录触发 dispatch('user/login'),来看一下这里面发生了什么
1 commit('SET_TOKEN', data.token) 2 setToken(data.token) 3 //登录获取信息把token存起来
刚才permission中
const { roles } = await store.dispatch('user/getInfo')
//getInfo通过存起来的token获取用户信息 //根据用户动态生成路由 const accessRoutes = await store.dispatch('permission/generateRoutes', roles)//获取到action动态生成的路由 router.addRoutes(accessRoutes)
权限判断中
1 generateRoutes({ commit }, roles) { 2 return new Promise(resolve => { 3 let accessedRoutes 4 //用户是admin拥有所有权 5 if (roles.includes('admin')) { 6 accessedRoutes = asyncRoutes || [] 7 } else { 8 //不是超级管理员进入filterAsyncRoutes函数判断 9 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) 10 } 11 commit('SET_ROUTES', accessedRoutes)//把动态生成路由存起来 12 resolve(accessedRoutes)//返回生成动态路由 13 }) 14 }
1 export function filterAsyncRoutes(routes, roles) { 2 const res = [] 3 4 routes.forEach(route => { 5 const tmp = { ...route } 6 debugger 7 if (hasPermission(roles, tmp)) { 8 if (tmp.children) { 9 tmp.children = filterAsyncRoutes(tmp.children, roles) 10 } 11 //满足条件存起来 12 res.push(tmp) 13 } 14 }) 15 16 return res 17 }
1 function hasPermission(roles, route) { 2 //判断路由是否存在与用户相同权限将会返回true 3 //路由不需要角色判断也会返回true 4 5 if (route.meta && route.meta.roles) { 6 return roles.some(role => route.meta.roles.includes(role)) 7 } else { 8 return true 9 } 10 }