【vue.js】vue后台项目权限功能实现思路
常見的后臺(tái)系統(tǒng)中,會(huì)存在不同的用戶角色,如超級(jí)管理員、普通用戶,這些用戶角色的權(quán)限是不同的,所以可以操作或顯示的模塊也不一致。這里采用如下后臺(tái)管理系統(tǒng)框架作為模板
地址:https://github.com/PanJiaChen/vue-admin-template
簡單說下需求,后臺(tái)菜單如下圖,要求系統(tǒng)中存在兩類用戶,管理員和普通員工,管理員登錄系統(tǒng)可見所有菜單選項(xiàng),普通用戶僅可見首頁菜單項(xiàng)。
項(xiàng)目左側(cè)菜單Sidebar組件代碼如下,用v-for遍歷當(dāng)前路由實(shí)例路由配置this.$router.options.routes傳遞給<sidebar-item/>,進(jìn)行展示,這里不做詳細(xì)介紹,
<el-scrollbar wrap-class="scrollbar-wrapper"><el-menu:default-active="activeMenu":collapse="isCollapse":background-color="variables.menuBg":text-color="variables.menuText":unique-opened="false":active-text-color="variables.menuActiveText":collapse-transition="false"mode="vertical"><sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" /></el-menu></el-scrollbar><script> import { mapGetters } from 'vuex' import Logo from './Logo' import SidebarItem from './SidebarItem'export default {components: { SidebarItem, Logo },computed: {...mapGetters(['sidebar']),routes() {return this.$router.options.routes;},} }由此可知要實(shí)現(xiàn)菜單欄的動(dòng)態(tài)展示,在路由配置文件中,就不能將項(xiàng)目中所有的路由配置對(duì)象寫在一起,這里將項(xiàng)目中的路由配置拆分成三類,如下所示。分別是constantRoutes常量路由,存放所有用戶都可見的路由包括首頁,登錄頁,404頁;asyncRoutes異步路由,存放不同的用戶需要過濾出篩選的路由;anyRoutes任意路由,當(dāng)路徑出現(xiàn)錯(cuò)誤的時(shí)候重定向到404頁面。這樣就可以靈活處理路由配置信息了。
router/index.js
export const constantRoutes = [{path: '/login',component: () => import('@/views/login/index'),hidden: true},{path: '/404',component: () => import('@/views/404'),hidden: true},{path: '/',component: Layout,redirect: '/dashboard',children: [{path: 'dashboard',name: 'Dashboard',component: () => import('@/views/dashboard/index'),meta: { title: '首頁', icon: 'dashboard' }}]},]export const asyncRoutes = [{name: 'Acl',path: '/acl',component: Layout,redirect: '/acl/user/list',meta: {title: '權(quán)限管理',icon: 'el-icon-lock'},children: [{name: 'User',path: 'user/list',component: () => import('@/views/acl/user/list'),meta: {title: '用戶管理',},},......]},{path:'/product',component:Layout,name:'Product',meta: { title: '商品管理', icon: 'el-icon-goods' },children:[{path:'tradeMark',name:'TradeMark',component:() => import('@/views/product/tradeMark'),meta:{title:'品牌管理'}},......]}, ];export const anyRoutes = [// 404 page must be placed at the end !!!{ path: '*', redirect: '/404', hidden: true } ];const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes })在用戶登錄系統(tǒng)后,瀏覽器會(huì)根據(jù)用戶的token信息獲取用戶的詳細(xì)信息,里面除了用戶的基本信息外,還包括該用戶可以訪問的菜單列表(Array),以及用戶能夠操作的按鈕列表。
請(qǐng)求行為在vuex的actions中進(jìn)行,在登錄頁面派發(fā)該actons,在aciions中將響應(yīng)的用戶信息提交mutations。
const getDefaultState = () => {return {token: getToken(),name: '',avatar: '',routes:[], // 服務(wù)器返回的菜單標(biāo)記信息buttons:[], // 服務(wù)器返回的按鈕標(biāo)記信息role:[], // 服務(wù)器返回的角色信息} }const state = getDefaultState() const mutations = {RESET_STATE: (state) => {Object.assign(state, getDefaultState())},USER_INFO: (state,info) => {state.name = info.name;state.avator = info.avator;state.routes = info.routes; // 菜單權(quán)限標(biāo)記state.buttons = info.buttons; // 按鈕權(quán)限標(biāo)記state.role = info.role; // 用戶角色 }, const actions = {// get user infogetInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {const { data } = responseif (!data) {return reject('Verification failed, please Login again.')}// commit('USER_INFO',data);resolve(data)}).catch(error => {reject(error)})})}, }拿到了服務(wù)器返回的可顯示的異步路由標(biāo)記信息后,接下去要做的就是將其和項(xiàng)目中所有的異步路由信息進(jìn)行對(duì)比,得到最終需要展示的異步路由信息,這里在登錄后再提交一個(gè)mutations,命名為SEY_RESULTASYNCROUTES,傳給mutations一個(gè)方法computedAsyncRoutes,在這個(gè)方法中做路由的信息對(duì)比,將當(dāng)前用戶要顯示的異步路由作為返回值返回。
getInfo({ commit, state }) {return new Promise((resolve, reject) => {getInfo(state.token).then(response => {const { data } = responseconsole.log(response.data);if (!data) {return reject('Verification failed, please Login again.')}// commit('USER_INFO',data);commit('SEY_RESULTASYNCROUTES',computedAsyncRoutes(asyncRoutes,data.routes));resolve(data)}).catch(error => {reject(error)})})},定義computedAsyncRoutes方法如下,將異步路由asyncRoutes引入,遍歷asyncRoutes數(shù)組,將每一個(gè)路由的name和服務(wù)器傳來的標(biāo)記信息routes挨個(gè)對(duì)比(indexOf方法),過濾出服務(wù)器標(biāo)記數(shù)組中包含的路由信息;
這里值得注意一點(diǎn),由于路由存在二級(jí)甚至三級(jí)路由,這些路由是寫在路由配置對(duì)象的children屬性中,它們一樣也要遍歷并對(duì)比判斷它們是否需要顯示,需要遞歸調(diào)用computedAsyncRoutes方法,對(duì)每個(gè)以及路由的children再次進(jìn)行過濾。
import { resetRouter,asyncRoutes,anyRoutes,constantRoutes } from '@/router' // 兩個(gè)數(shù)組進(jìn)行對(duì)比,計(jì)算出當(dāng)前用戶顯示哪些異步路由 const computedAsyncRoutes = (asyncRoutes,routes) => {return asyncRoutes.filter((item) => {// 服務(wù)器返回的數(shù)組中包含的路由信息if(routes.indexOf(item.name) !== -1) {// 如果存在多級(jí)路由,遞歸if(item.children && item.children.length) {item.children = computedAsyncRoutes(item.children,routes);}return true;}}) }這樣提交到的SEY_RESULTASYNCROUTES這個(gè)mutations中就可以拿到上述處理完后的路由配置信息asyncRoutes了,但還需要做路由的合并操作,就是將先前定義的常量路由、任意路由和剛剛對(duì)比過濾完的異步路由三者進(jìn)行合并(數(shù)組的concat方法),形成一個(gè)最終完整的路由信息,并給當(dāng)前項(xiàng)目添加這個(gè)路由規(guī)則router.addRoutes(state.resultAllRoutes)
import router from '@/router' const getDefaultState = () => {return {token: getToken(),name: '',avatar: '',routes:[], // 服務(wù)器返回的菜單標(biāo)記信息buttons:[], // 服務(wù)器返回的按鈕標(biāo)記信息role:[], // 服務(wù)器返回的角色信息resultAsyncRoutes:[],resultAllRoutes:[]} }const state = getDefaultState();mutations:{// 最終計(jì)算出的異步路由SEY_RESULTASYNCROUTES(state,asyncRoutes){// vuex保存當(dāng)前用戶的異步路由state.resultAsyncRoutes = asyncRoutes;// 計(jì)算出當(dāng)前用戶的所有路由state.resultAllRoutes = constantRoutes.concat(state.resultAsyncRoutes,anyRoutes);// 給路由添加新的路由router.addRoutes(state.resultAllRoutes);} }此時(shí)登陸后依舊無法正確顯示左側(cè)的菜單。
雖然此時(shí)正確的路由已經(jīng)存在于router實(shí)例中,但左側(cè)導(dǎo)航欄<Sidebar>組件遍歷的依舊只有首頁菜單,那是因?yàn)樵趓outes/index.js中注冊(cè)是常量路由如下所示,而修改操作router.addRoutes(state.resultAllRoutes)是異步操作以后的結(jié)果,在sidebar組件中通過?this.$router.options.routes只能獲取初始的常量路由
?router/index.js:
const createRouter = () => new Router({// mode: 'history', // require service supportscrollBehavior: () => ({ y: 0 }),routes: constantRoutes })sidebar.vue
export default {components: { SidebarItem, Logo },computed: {routes() {return this.$router.options.routes;},} }只需將獲取方式改為倉庫中最新的路由配置信息this.$store.state.user.resultAllRoutes
sidebar.vue
routes() {return this.$store.state.user.resultAllRoutes; },這樣就實(shí)現(xiàn)了不同身份的用戶登錄后顯示不同的菜單的效果。
此外,要在項(xiàng)目中實(shí)現(xiàn)按鈕權(quán)限,即同一個(gè)按鈕,有的用戶顯示按鈕,有的用戶不顯示,只要拿到上述的buttons數(shù)組,在對(duì)應(yīng)的按鈕標(biāo)簽上使用v-show進(jìn)行判斷即可
<button v-show="$store.state.xxxModule.buttons.indexOf('對(duì)應(yīng)的按鈕標(biāo)簽名')">刪除</button>總結(jié)
以上是生活随笔為你收集整理的【vue.js】vue后台项目权限功能实现思路的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Vue.js】vue2组件间通信方式总
- 下一篇: html5倒计时秒杀怎么做,vue 设