日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue实现页面权限显示_vue实现菜单权限控制

發布時間:2025/1/21 vue 68 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue实现页面权限显示_vue实现菜单权限控制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家在做后臺管理系統時一般都會涉及到菜單的權限控制問題。當然解決問題的方法無非兩種——前端控制和后端控制。我們公司這邊的產品迭代速度較快,所以我們是從前端控制路由迭代到后端控制路由。下面我會分別介紹這兩種方法的優缺點以及如何實現(不熟悉vue-router API的同學可以先去官網看一波API哈)。

我先簡單說下項目的需求:如下圖所示,有一級菜單和二級菜單,然后不同的人登錄進去會展示不同的菜單。

前端控制路由的思路:將所有的路由映射表都拿到前端來維護,就是我的router.js里面將所有的菜單path與對應的components全部寫進去,后面我會提到全部寫進去的弊端。然后我的左側菜單寫成一個組件(sidebar.vue),在這個組件里寫一份類似這樣的data數據,然后通過登錄時獲取的level值來給data中固定的菜單加hidden,然后前端就根據hidden展示菜單。

//router.js 偽代碼

const Login= r => require.ensure([],()=>r(require('../page/login/Login.vue')),'login');

const Home= r => require.ensure([],()=>r(require('../page/Home.vue')),'home');

const Forbidden= r => require.ensure([],()=>r(require('../page/403.vue')),'forbidden');

const NotFound= r => require.ensure([],()=>r(require('../page/404.vue')),'notfound');

const Dashboard= r => require.ensure([],()=>r(require('../page/dashboard/Dashboard.vue')),'dashboard');

const SplashScreen= r => require.ensure([],()=>r(require('../page/splashScreen/SplashScreen.vue')),'splashScreen');

const AddSplashScreen= r => require.ensure([],()=>r(require('../page/splashScreen/AddSplashScreen.vue')),'addSplashScreen');

const routes=[

{

path:'/',

redirect:'/login'},{

path:'/login',

component: Login

},{

path:'/404',

component: NotFound

},{

path:'/home',

component: Home,

redirect:'/home/splashScreen',

children: [

{

path:'/home/splashScreen',

component: SplashScreen,

meta: {

title:'國服李白

}

},{

path:'/home/addSplashScreen',

component: AddSplashScreen,

meta: {

title: 國服呂布'}

}

]

}

];

下面是菜單組件的偽代碼

//sidebar.vue

...

data() {return{

routes: [

{

index:'1',

title:'國服打野',

icon:'iconfont icon-guanggao',

children: [

{

index:'splashScreen',

title:'李白',

children: []

},

]

},

{

index:'2',

title:'國服中單',

icon:'iconfont icon-tuisongguanli-',

}

]

}

},

methods: {

getLevel(){

const level= sessionStorage.getItem('level');if(level === '0'){this.routes.forEach(function(value){if(value.title == "國服上單"){

value.hidden= true;

value.children.forEach(function(value){if(value.title=="國服關羽"){

value.hidden= true;

}

})

}

})

}else if(level === '1'){this.routes.forEach(function(value){

value.hidden= truevalue.children.forEach(function(value){

value.hidden= true;

})

})

}

}

},

created(){this.getLevel();

}

}

雖然說這樣可以實現權限功能,但有兩個問題。

session里存的是level,我們可以打開瀏覽器控制臺人為控制level,這樣就失去了權限的意義。

我們如果記住了path,可以直接在瀏覽器網址欄中手動輸入path,然后回車就可以看到任何頁面。這也是前端router.js寫死所有路由的弊端。

在這里面前端只是通過后端傳回的level來給router顯示/隱藏,這樣前端維護整個路由是比較復雜的而且是有重大隱患的。

現在呢我們來講講后端控制路由。先從操作流程來說,我們這邊加入了一個dashboard中間頁,這個頁面只展示不同level下的一級路由,通過點擊相應的一級路由進到對應的Page頁面,該page頁面也只展示相對應的所有的二級路由。

這里面出現了兩個個新的概念叫 “動態添加路由”和“導航守衛”,就是我前端router.js中只寫所有人可以訪問的路由表,比如login和404頁面等。其他所有的組件資源全部寫到一個新的components.js文件中,然后通過后端返回的menuData去映射符合components.js中的key,如果有對應的,就把它動態添加到router中,通過addRoutes添加。動態添加路由這個方法要寫到導航守衛beforeEach這個鉤子函數中。導航守衛的意思是我路由跳轉到下個頁面之前要做些什么。就是說我們登錄后會跳到dashboard頁面,在進到這個頁面之前我們需要將后端請求回來的menuData進行二次封裝,把他根據權限返回回來的data與我們前端components.js去做map匹配,將最終的數據通過addRoutes來push到我們的路由中,之后才能進到我們的dashborad頁面,再通過dashborad頁面進到對應的page頁面,就是說我們把所有的權限控制全在dashboard頁面進入之前就做完了。這里面還有一個小的優化的點:當我們通過前面說的瀏覽器菜單欄訪問到非權限頁面或者不存在的頁面時,需要根據vue-router中的匹配優先級來最后addRoutes 404和*這個頁面,這樣就可以直接到達404頁面而非空頁面。

//components.js 所有的頁面資源

const home = () => import('../page/Home.vue');

const splashScreen= () => import('../page/splashScreen/SplashScreen.vue');

const addSplashScreen= () => import('../page/splashScreen/AddSplashScreen.vue');

const editSplashScreen= () => import('../page/splashScreen/EditSplashScreen.vue');

exportdefault{

home,

splashScreen,

addSplashScreen,

editSplashScreen,

};

//router.js 看,只寫通用的頁面是不是很清爽

import Vue from 'vue';

import Router from'vue-router';

Vue.use(Router);

const Login= () => import('../page/login/Login.vue');

const Home= () => import('../page/Home.vue');

const Forbidden= () => import('../page/403.vue');

const Dashboard= () => import('../page/dashboard/Dashboard.vue');

const routes=[

{

path:'/',

redirect:'/login'},{

path:'/login',

component: Login

},{

path:'/403',

component: Forbidden

},

{

path:'/dashboard',

component: Dashboard,

},

];

exportdefault newRouter({

mode:'history',

routes: routes,

base: __dirname,

linkActiveClass:'link-active'})

//main.js 偽代碼 只保留具體的相關邏輯

import routeMap from './router/component.js';

const NotFound= () => import('./page/404.vue');

const formatRoutes= function(routes, routeData) {if (!routeData) {

routeData={

name:'home',

path:'/home',//組件匹配成功的話才可以訪問具體的頁面

component: routeMap['home'],

children: [],

};

}

routes.length&& routes.forEach(route =>{if(route.component) {

route.component=routeMap[route.component];

routeData.children.push({

path: route.path,

name: route.index,

component: route.component,

meta: {

title: route.title,

},

})

}if (route.children &&route.children.length) {

formatRoutes(route.children, routeData);

}

});returnrouteData;

};

let isFetchRemote= true;//使用鉤子函數對路由進行權限跳轉

router.beforeEach((to, from, next) =>{

const username= sessionStorage.getItem('username');if(!username && to.path !== '/login'){

next({path:'/login'});

}else if (isFetchRemote && to.path !== '/login') {

ajaxPost('/resourceAPI/getMenuData').then(res =>{if (res.status === 200 && res.data.errno === 0) {

isFetchRemote= false;

const menuData=res.data.result;

localStorage.setItem('menudata', JSON.stringify(menuData));

const routeData=formatRoutes(menuData);

resourceApp.$router.addRoutes([routeData].concat([

{name:'404',path:'/404',component:NotFound},

{path:'*',redirect: '/404'}]));

resourceApp.$router.push({

path: to.path,

query: to.query

});

}else{

isFetchRemote= true;

}

next();

})

.catch(err =>{

console.log(err);

});

}else{

next();

}

});

const resourceApp= newVue({

router,

render: h=>h(App)

}).$mount('#app');

//menuData請求數據//一級菜單與二級菜單的區別是一級菜單帶有component這個值,比如下面的短信管理就是只有一級菜單

{"errno": 0,"errmsg": "獲取權限成功","result": [

{"index": "1","title": "打野位置","icon": "iconfont icon-guanggao","children": [

{"index": "splashScreen","icon": "","title": "娜可露露","path": "/home/splashAdverse","component": "splashAdverse","isShow": true},

{"index": "addSplashScreen","icon": "","title": "李白","path": "/home/addAdverse","component": "addAdverse","isShow": false},

]

},

{"index": "message","title": "國服上單","icon": "iconfont icon-duanxinguanli","path": "/home/message","component": "message","children": [

{"index": "addMessage","title": "國服第一關羽","icon": "","path": "/home/addMessage","component": "addMessage","isShow": false}

]

}

]

}

而sidebar和dashboard這兩個組件都只需要通過session拿到后端的menudate就可以。

//dashboard 偽代碼

{{item.title}}

const routeArr= JSON.parse(localStorage.getItem('menudata'));this.navList =routeArr;

},

methods: {

goPage(item){//只有一級菜單

if(item.component){this.$router.push(item.path);

}else{//二級菜單的數據結構中只在children中有path

this.$router.push(item.children[0]['path']);

}

}

}

//sidebar 偽代碼

data() {return{

routes: [],

}

},

methods: {

bouncer(arr){return arr.filter(function(val){return !(!val || val === "");

});

}

},

created(){

const menuData= JSON.parse(localStorage.getItem('menudata'));//通過當前router的path來map對應的整個路由數組

let routes = menuData.map((item)=>{//只有一級路由

if(item.component && item.path == this.$route.path){

console.log(item)returnitem;

}else{if(item.children[0]['path'] == this.$route.path){

console.log(item)returnitem;

}

}

})//去掉數組中的undefined、null 等空值 假值

this.routes = this.bouncer(routes);

}

}

通過這種方式來控制權限,我們如果在瀏覽器控制臺改了session中的level或者在瀏覽器導航欄改path,都會回歸到導航守衛中,就是發請求重新獲取menuData,當我addRoutes后如果沒有匹配到這個值就回到404,當然通過改level也不會達到修改權限的控制,因為我們是動態獲取路由,不是之前的前端控制路由。

目前為止,我感覺通過后端控制權限這種實現方式應該是最理想的一種吧,當然大家有更好的方法或者對此文有任何問題,歡迎大家留言哈。

總結

以上是生活随笔為你收集整理的vue实现页面权限显示_vue实现菜单权限控制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。