vue控制臺基本實現(xiàn)

根據(jù)登錄狀態(tài)和用戶的角色設(shè)置路由攔截是控制臺的基本功能,本文主要是對這部分內(nèi)容的總結(jié),閱讀這篇文章之后,你可以構(gòu)建一個基本功能完整的控制臺。

項目倉庫地址

路由守衛(wèi)

登錄狀態(tài)的處理

用戶未登錄時,攔截用戶的所有路由,跳轉(zhuǎn)登錄頁面,而在登錄之后,用戶不應(yīng)該再進入登錄頁面,將頁面重定向到首頁

Const whiteList = [‘/login’] // 使用白名單放置不登錄也可以訪問的頁面,現(xiàn)在只有登錄頁
router.beforeEach((to, from, next) => {
  const hasToken = getToken()
  if (hasToken) {
    if (to.path === ‘/login’) {
      next({ path: ‘/‘ })
    } else {
      next()
    }
  } else {
    if (whiteList) {
      if (whiteList.includes(to.path)) {
        next()
      } else {
        next('/login')
      }
    }
  }
})
未登錄攔截路由

用戶角色的處理

一般我們項目中不但要根據(jù)用戶的登錄狀態(tài)限制路由,也存在根據(jù)用戶角色限制路由的場景。
首先要在路由的meta中設(shè)置roles屬性,roles設(shè)置為進入路由需要的用戶角色,然后再在路由跳轉(zhuǎn)時,添加用戶角色的處理邏輯:

const needRoles = to.meta && to.meta.roles && to.meta.roles.length > 0
  if (needRoles) {
    const hasRoles = store.state.user.roles.some(role => to.meta.roles.includes(role))
    if (hasRoles) {
      next()
    } else {
      next('/403')
    }
  } else {
    next()
  }
image

菜單欄實現(xiàn)

不同角色的用戶登錄控制臺,因為角色擁有的權(quán)限不同我們應(yīng)該展示給用戶不同的菜單,在實現(xiàn)路由守衛(wèi)的時候,我們在路由的meta上通過設(shè)置roles屬性限制了不同角色的權(quán)限,這個權(quán)限的限制與菜單欄的顯示權(quán)限的限制應(yīng)該是一致的。所以我們可以使用路由和獲取的用戶角色來生成菜單欄菜單。

/**
 * 根據(jù)路由meta.role確定是否當前用戶擁有訪問權(quán)限
 * @roles 用戶擁有角色
 * @route 待判定路由
 */
function hasPermission (roles, route) {
  // 如果當前路由有roles字段則需判斷用戶訪問權(quán)限
  if (route.meta && route.meta.roles) {
    // 若用戶擁有的角色中有被包含在待判定路由角色表中的則擁有訪問權(quán)
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    // 沒有設(shè)置roles則無需判定即可訪問
    return true
  }
}

/**
 * 遞歸過濾AsyncRoutes路由表
 * @routes 待過濾路由表,首次傳入的就是AsyncRoutes
 * @roles 用戶擁有角色
 */
export function filterAsyncRoutes (routes, roles) {
  const res = []

  routes.forEach(route => {
    // 復(fù)制一份
    const tmp = { ...route }
    // 如果用戶有訪問權(quán)則加入結(jié)果路由表
    if (hasPermission(roles, tmp)) {
      // 如果存在子路由則遞歸過濾之
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

filterAsyncRoutes(asyncRoutes, state.roles)

我們使用roles過濾生成新的路由后會發(fā)現(xiàn),生成的路由直接作為菜單項還是存在一些問題,例如數(shù)據(jù)詳情頁面往往是不在菜單欄中展示的,所以過濾后的路由直接作為菜單項依舊不是很合適,所以需要再進行處理,通過路由的hidden屬性再次進行過濾。

const filterMenu = (route) => {
  const children = route.children ? route.children.filter(item => !item.hidden) : []
  if (children.length === 0) {
    return {
      icon: route.meta.icon, name: route.name, title: route.meta.title
    }
  }
  if (children.length === 1) {
    // 單只有一個子菜單的時候,子菜單會被提升
    return filterMenu(children[0])
  }
  if (children.length > 1) {
    return {
      icon: route.meta.icon, name: route.name, title: route.meta.title, subs: children.map(filterMenu)
    }
  }
}

請求處理

發(fā)送請求也是項目中必不可少的的功能,在項目中我們通常使用axios來發(fā)送請求,針對請求我們在請求發(fā)送之前和接受請求時進行處理。

http.interceptors.request.use(
  config => {
    config.headers['token'] = getToken()
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

http.interceptors.response.use(
  response => {
    if (response.status !== 200) {
      return Promise.reject(response)
    }
    // 處理狀態(tài)碼
    const data = response.data
    if (data.code === 10000) {
      // setToken(cookies)
      return data
    }
    // 1006為用戶未登錄
    if (data.code === 10006) {
      MessageBox.alert('登錄狀態(tài)異常,請重新登錄', '確認登錄信息', {
        confirmButtonText: '重新登錄',
        type: 'warning',
        callback: () => {
          removeToken()
          router.replace({ name: 'login' })
        }
      })
      return Promise.reject(new Error(data))
    }
    // 其他錯誤碼,提示信息并返回信息
    Message({
      message: data,
      type: 'error',
      duration: 3 * 1000
    })
    return Promise.reject(new Error(data))
  },
  error => {
    Message({
      message: error.message,
      type: 'error',
      duration: 3 * 1000
    })
    return Promise.reject(error)
  }
)

這里主要是對返回的結(jié)果進行處理,根據(jù)不同的錯誤類型進行分類處理,比較要代表性的是登錄狀態(tài)失效的處理,和其他錯誤不同,登錄失效會直接讓用戶進入登錄頁面。

其他

  1. 菜單欄的收起與展開:在store的state中添加collapse進行控制,在Header組件中根據(jù)頁面寬度進行collapse的初始設(shè)置。
if (document.body.clientWidth < 980) {
  this.$store.commit('changeCollapse', true)
}
  1. 標簽頁的控制:標簽頁的標簽頁列表也放到store中,這樣用戶在頁面里需要關(guān)閉標簽頁時,就可以調(diào)用方法進行關(guān)閉了。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 使用全局路由守衛(wèi) 實現(xiàn) 前端定義好路由,并且在路由上標記相應(yīng)的權(quán)限信息 全局路由守衛(wèi)每次都判斷用戶是否已經(jīng)登錄,沒...
    若邪Y閱讀 30,983評論 4 54
  • element-ui 文檔 Vue項目接口文檔地址 博客 session 和 cookie等 學什么? 1 如何使...
    cj_jax閱讀 4,076評論 0 10
  • 學習總結(jié)vue后臺管理系統(tǒng) 后臺頁面的權(quán)限驗證與安全性是非常重要的,可以說是一個后臺項目一開始就必須考慮和搭建的基...
    尋心途閱讀 2,419評論 0 4
  • 兒時 兩小辮的丑小鴨 小眼睛 怯怯望炊煙茫茫 手拉手一起上學堂 腳跟腳爬過泥土崗 看瓜果飄香 走過 月亮的...
    飛翔羽天閱讀 357評論 1 4
  • 人很奇怪的保持著微妙的一種平衡,來時如風去時似雨。 一只貓掉了進來,其實我對貓的喜愛不如對狗,總覺得人說貓高冷且無...
    錫鹿閱讀 254評論 0 0

友情鏈接更多精彩內(nèi)容