欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

手把手教學(xué)vue的路由權(quán)限問題

 更新時間:2022年12月01日 15:10:39   作者:哆來A夢沒有口袋  
這篇文章主要介紹了手把手教學(xué)vue的路由權(quán)限問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

后臺管理類系統(tǒng)大多都涉及權(quán)限管理,菜單權(quán)限,按鈕權(quán)限。

菜單權(quán)限

菜單權(quán)限對應(yīng) - 路由。菜單權(quán)限 - 根據(jù)用戶角色不同,路由文件動態(tài)配置。

相關(guān)知識點了解

vue-router

vue-router是vue項目在進(jìn)行開發(fā)過程中必不可少缺少的插件,目前vue2依賴的是vue-router3,vue3依賴的vue-router4

在進(jìn)行權(quán)限控制之前一定要了解哪些路由需要權(quán)限哪些不需要

知識點集結(jié)

  • router.addRoutes()

動態(tài)添加更多的路由規(guī)則。參數(shù)必須是一個符合 routes 選項要求的數(shù)組。

已廢棄目前版本再使用該api會被提示已經(jīng)廢棄,但是暫時依舊可以使用

router.addRoutes(routes: Array<RouteConfig>)
  • router.addRoute()

添加一條新路由規(guī)則。如果該路由規(guī)則有 name,并且已經(jīng)存在一個與之相同的名字,則會覆蓋它。

addRoute(route: RouteConfig)
  • router.getRoutes()

獲取所有活躍的路由記錄列表。注意只有文檔中記錄下來的 property 才被視為公共 API,避免使用任何其它 property,例如 regex,因為它在 Vue Router 4 中不存在。

路由導(dǎo)航守衛(wèi) - beforeEach

router.beforeEach((to, from, next) => {
  /* 必須調(diào)用 `next` */
})

全局前置守衛(wèi) - 跳轉(zhuǎn)一個路由之前都會執(zhí)行.

3個參數(shù):

  • to: 即將進(jìn)入的目標(biāo)的路由對象
  • from:當(dāng)前導(dǎo)航正在離開的路由
  • next: 是個函數(shù),進(jìn)入下一個鉤子
  • next(): 進(jìn)行管道中的下一個鉤子。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是 confirmed (確認(rèn)的)。
  • next(false): 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應(yīng)的地址。
  • next('/') 或者 next({ path: '/' }): 跳轉(zhuǎn)到一個不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個新的導(dǎo)航。你可以向 next 傳遞任意位置對象,且允許設(shè)置諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
  • next(error): (2.4.0+) 如果傳入 next 的參數(shù)是一個 Error 實例,則導(dǎo)航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調(diào)。

功能實現(xiàn)過程

路由權(quán)限第一種可以是后端全部返回,直接調(diào)用接口使用后端的可以使用的路由,但是這種情況一般較少。

第二種前端有一個份完整路由,根據(jù)后端接口進(jìn)行篩選,這里講解第二種情況。

(1)定義路由文件

router -> index.js

import Vue from 'vue'
import Router from 'vue-router'
import store  from '../store'
 
Vue.use(Router)
 
//沒有權(quán)限的路由
export const constantRoutes = [
  { path: '/', name: 'index', redirect: '/login' },
  { path: '/login', name: 'login', component: () => import('@/views/login') },
  { path: '/register', name: 'register', component: () => import('@/views/register') },
  { path: '/forget', name: 'forget', component: () => import('@/views/forget') },
  { path: '/404', name: 'notfing', component: () => import('@/views/404')}
]
 
//有權(quán)限的路由
export const  myAsyncRoute = [{
  path: '/portal',
  name: 'portal',
  component: LayoutPortal,
  redirect: '/portal/home',
  meta: {id: 'no'},
  children: [
    {
      path: '/portal/home',
      name: 'portal-home',
      component: () => import('@/views/portal/home/index.vue'),
      meta: {id: 100100, title: '首頁', show: true}
    },
    {
      path: '/portal/user',
      name: 'portal-user',
      component: () => import('@/views/layout/submenu'),
      meta: {id: 100200, title: '統(tǒng)一身份認(rèn)證', show: true},
      redirect: '/portal/user/userInfo',
      children: [
        {
          path: '/portal/user/userInfo',
          name: 'portal-user-userInfo',
          component: () => import('@/views/portal/userInfo/index.vue'),
          meta: {id: 100201, title: '統(tǒng)一用戶管理', show: true}
        },
        {
          path: '/portal/user/userInfo/detial',
          name: 'portal-userInfo-detial',
          component: () => import('@/views/portal/userInfo/detial.vue'),
          meta: { id: 100201, activeMenu: '/portal/user/userInfo', title: '統(tǒng)一用戶管理', show: false},
        },
        {
          path: '/portal/user/userAuth',
          name: 'portal-user-userAuth',
          component: () => import('@/views/portal/userAuth/index.vue'),
          meta: {id: 100202, title: '用戶認(rèn)證', show: true}
        },
      ]
    },
    {
      path: '/portal/journal',
      name: 'portal-journal',
      component: () => import('@/views/portal/journal/index.vue'),
      meta: {id: 100303, title: '統(tǒng)一日志管理', show: true},
    },
    {
      path: 'personal',
      name: 'portal-personal',
      component: () => import('@/views/portal/personal/index.vue'),
      meta: {
        id: 'no',
        activeMenu: '/portal/home',
        show: false
      },
    },
  ],
}]
 
export default new Router({
  routes: constantRoutes,
})

(2)注冊路由

main.js

import router from './router'
 
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

正常注冊完路由就可以開始進(jìn)行權(quán)限設(shè)置了

(3)獲取有權(quán)限路由

不同的項目獲取路由權(quán)限并不相同,大多數(shù) - 登錄接口返回/單獨接口進(jìn)行獲取

登錄獲取權(quán)限保存

let res = await this.$api.user.login(data);
 if(res.token) {
      this.$store.commit('setToken', res.token);
      this.$store.commit('setUsername', res.nickName);
      this.$store.commit('setUserInfo', res);
      //存儲權(quán)限
      localStorage.setItem('menuIdList', JSON.stringify(res.menuIdList))
           this.$message({
              message: '登錄成功',
              type: 'success'
            });
 
            setTimeout(() => {
               this.loading = false;
               this.$router.push('/portal')
            }, 1000);
   }

在main.js中攔截 

獲取權(quán)限進(jìn)行匹配 - beforeEach一定要有一個next()的出口,不然會陷入死循環(huán)

let flag = true;
router.beforeEach((to, from, next) => {
  if (['/login', '/forget', '/register'].includes(to.path)) {
    next();
  } else {
    let token = localStorage.getItem("token");
    if (token) {
      if(flag) {
        try {
          //獲取有權(quán)限的路由進(jìn)行組裝
          let route = asyncRoute() || [];
          router.addRoutes(route)
          router.addRoute({
            path: '*',
            redirect: '/404'
          })
          flag = false
          next({...to, replace:true})
        }catch(e) {
          next('/login')
        }
       }else {
         next();
       }
      }else {
        next({ path: '/login' })
      }
    }
  }
);

注意: addRoute之后,打印router是看不見的,要獲取所有的權(quán)限,必須使用router.getRoute()進(jìn)行查看

(4)路由權(quán)限匹配

router.js-根據(jù)后端返回的權(quán)限,和自己的路由權(quán)限匹配,組織成新的路由,和自己想要的格式

export const asyncRoute = function() {
  let menuIdList = localStorage.getItem('menuIdList') ? JSON.parse(localStorage.getItem('menuIdList')) : [];
 
  let tempArr = filterRoute(myAsyncRoute, menuIdList);
 
  store.dispatch('getRoute', tempArr)
 
  let showRoute = [];
  let nowRoute =JSON.parse(JSON.stringify(tempArr))
  if(nowRoute[0].children && nowRoute[0].children.length){
    nowRoute[0].children.forEach(item => {
      let arr = [];
      if(item.children && item.children.length){
        arr = item.children.filter(obj => obj.meta.show)
      }
      if(item.meta.show){
        item['showRouteChildren'] = arr;
        showRoute.push(item)
      }
    })
  }
  store.dispatch('getShowRoute', showRoute)
 
  return tempArr
}
 
 
function filterRoute(arr, menuIdList) {
  if(!arr.length) return [];
  return arr.filter(item => {
    if(item.children && item.children.length) {
      item.children = filterRoute(item.children, menuIdList);
    }
    return (item.meta && item.meta.id && menuIdList.includes(item.meta.id)) || (item.meta && item.meta.id == 'no') || (item.children && item.children.length > 0)
  })
}

在這個過程中,在store存儲了路由

import Vue from 'vue'
import Vuex from 'vuex'
 
Vue.use(Vuex)
 
export default new Vuex.Store({
    state: {
        routes: JSON.parse(localStorage.getItem('routes')) ||  [],
        addRoutes: JSON.parse(localStorage.getItem('addRoutes')) ||[],
        showRoutes: []
    },
    mutations: {
        setRoutes(state, routes) {
            state.addRoutes = routes;
            state.routes = constantRoutes.concat(routes)
            localStorage.setItem('routes', JSON.stringify(state.routes))
            localStorage.setItem('addRoutes', JSON.stringify(state.addRoutes))
        },
        setShowRoutes(state, routes) {
            state.showRoutes = routes;
        }
    },
    actions: {
        getRoute({commit}, list) {
            return new Promise(resolve => {
                commit('setRoutes', list)
                resolve(list)
            })
        },
        getShowRoute({commit}, list) {
            return new Promise(resolve => {
                commit('setShowRoutes', list)
                resolve(list)
            })
        }
    }
})

總結(jié): 最后在理一下整個過程 - 存儲權(quán)限路由數(shù)據(jù),在進(jìn)行跳轉(zhuǎn)的時候進(jìn)行篩選組合路由。其實篩選路由不一定要寫在router.js,只要是你認(rèn)為合適的地方都可以,在權(quán)限控制過程中最重要的是路由攔截。

模擬一下路由攔截的過程

假設(shè)login之后進(jìn)入的/index,路由攔截的過程

/index - > token -> flag(true) ->獲取路由權(quán)限 -> next('/index') -> 重新進(jìn)入beforeEach-> token->flag(false) -> next() ->結(jié)束

按鈕權(quán)限 - 操作(自定義指令)

按鈕權(quán)限主要涉及的知識點就是全局自定義指令

寫在main.js。或者單獨js文件,main.js進(jìn)行引入

import Vue from "vue"
import store from "../store"
 
//自定義指令 v-has進(jìn)行權(quán)限判斷
Vue.directive("has",{
  inserted : function (el,binding){
    //按鈕權(quán)限
    const data = store.state.buttons;
    //按鈕的值 <el-button v-has>aa</el-button>
    const value = binding.value; //a
    const hasPermissions = data.includes(value);
    if(!hasPermissions){
       //隱藏按鈕
      el.style.display = "none";
      setTimeout(()=>{
        el.parentNode.removeChild(el)
      },0)
    }
  }
})

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue.js加載新的內(nèi)容(實例代碼)

    vue.js加載新的內(nèi)容(實例代碼)

    vue是一種輕巧便捷的框架,那么如何進(jìn)行對于數(shù)據(jù)加載的刷新呢?以下就是我對于vue.js數(shù)據(jù)加載的一點想法
    2017-06-06
  • Vue自定義復(fù)制指令 v-copy功能的實現(xiàn)

    Vue自定義復(fù)制指令 v-copy功能的實現(xiàn)

    這篇文章主要介紹了Vue自定義復(fù)制指令 v-copy,使用自定義指令創(chuàng)建一個點擊復(fù)制文本功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • vue使用axios?post發(fā)送json數(shù)據(jù)跨域請求403的解決方案

    vue使用axios?post發(fā)送json數(shù)據(jù)跨域請求403的解決方案

    這篇文章主要介紹了vue使用axios?post發(fā)送json數(shù)據(jù)跨域請求403的解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • vue.config.js中devServer.proxy配置說明及配置正確不生效問題解決

    vue.config.js中devServer.proxy配置說明及配置正確不生效問題解決

    Vue項目devServer.proxy代理配置詳解的是一個非常常見的需求,下面這篇文章主要給大家介紹了關(guān)于vue.config.js中devServer.proxy配置說明及配置正確不生效問題解決的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Vue.use()和Vue.prototype使用詳解

    Vue.use()和Vue.prototype使用詳解

    Vue.use()主要用于注冊全局插件,當(dāng)插件具有install方法時,調(diào)用Vue.use()可以全局使用該插件,Vue.prototype用于注冊全局變量,這些變量在項目任何位置都可以通過this.$變量名訪問,兩者的主要區(qū)別在于Vue.use()用于插件,Vue.prototype用于變量
    2024-10-10
  • vue實現(xiàn)二級彈框案例

    vue實現(xiàn)二級彈框案例

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)二級彈框案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • vue-element-admin 菜單標(biāo)簽失效的解決方式

    vue-element-admin 菜單標(biāo)簽失效的解決方式

    今天小編就為大家分享一篇vue-element-admin 菜單標(biāo)簽失效的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • Vue Vine實現(xiàn)一個文件中寫多個組件的方法(最近很火)

    Vue Vine實現(xiàn)一個文件中寫多個組件的方法(最近很火)

    Vue Vine提供了全新Vue組件書寫方式,主要的賣點是可以在一個文件里面寫多個vue組件,Vue Vine是一個vite插件,vite解析每個模塊時都會觸發(fā)插件的transform鉤子函數(shù),本文介紹Vue Vine是如何實現(xiàn)一個文件中寫多個組件,感興趣的朋友一起看看吧
    2024-07-07
  • Vue+axios 實現(xiàn)http攔截及路由攔截實例

    Vue+axios 實現(xiàn)http攔截及路由攔截實例

    這篇文章主要介紹了Vue+axios 實現(xiàn)http攔截及路由攔截 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Vue常見面試題整理【值得收藏】

    Vue常見面試題整理【值得收藏】

    本文是小編給大家收藏整理的Vue常見面試題,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-09-09

最新評論