vue權限路由詳解

前言css


近期,用vue框架作了個後臺管理項目,涉及權限,參考網上資料,得此項目https://github.com/zhangxuexi...
不知你們是否仍是各類mock工具來模擬數據,此項目,包含一個基於express,搭建的mock模擬服務,我的以爲,高大上了一點有木有!vue

clipboard.png

啓動node


mock項目:webpack

cd mock
npm install
npm start

基於node.js的mock服務就啓動起來了。

項目目錄git

clipboard.png

請求接口路由都在這個routes/index.js裏定義,接口返回的都是寫死的json數據。如需鏈接數據庫等操做請自行百度。這個項目不做重點介紹github

myProject項目:web

cd myProject
npm install
npm run dev

兩個項目分別啓動起來後,可用下面帳號登陸:
角色1:用戶名:123 密碼:a123456
角色2:用戶名:456 密碼:a123456vuex

router.js 權限路由
重點來了,直接上乾貨!數據庫

clipboard.png
這部分是webpack的代碼分割,模塊可按需加載,也就是懶加載,具體知識可點擊連接進去查看。express

clipboard.png

不授權限控制的通用路由可定義在這裏,直接在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,作狀態管理,仍是很方便的。
這段代碼流程:刷新或第一次訪問項目的時候,會請求這個接口,
clipboard.png

若是接口返回正確數據,說明是已登陸,繼續跳轉路由
若是未返回正確數據,則跳回登陸路由。

接口返回正確數據後,根據權限,去篩選路由

clipboard.png

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...

相關文章
相關標籤/搜索