1. 程式人生 > 其它 >element-admin的側邊欄導航和許可權

element-admin的側邊欄導航和許可權

技術標籤:vuevueelementui

element-admin的側邊欄引入方法

我的有道雲筆記可以下載:element-admin的側邊欄導航和許可權(下載檔案資源的附件)

側邊欄導航

配置項

// 當設定 true 的時候該路由不會在側邊欄出現 如401,login等頁面,或者如一些編輯頁面/edit/1
hidden: true // (預設 false)

//當設定 noRedirect 的時候該路由在麵包屑導航中不可被點選
redirect: 'noRedirect'

// 當你一個路由下面的 children 宣告的路由大於1個時,自動會變成巢狀的模式--如元件頁面
// 只有一個時,會將那個子路由當做根路由顯示在側邊欄--如引導頁面
// 若你想不管路由下面的 children 宣告的個數都顯示你的根路由
// 你可以設定 alwaysShow: true,這樣它就會忽略之前定義的規則,一直顯示根路由
alwaysShow: true

name: 'router-name' // 設定路由的名字,一定要填寫不然使用<keep-alive>時會出現各種問題
meta: {
  roles: ['admin', 'editor'] // 設定該路由進入的許可權,支援多個許可權疊加
  title: 'title' // 設定該路由在側邊欄和麵包屑中展示的名字
  icon: 'svg-name' // 設定該路由的圖示,支援 svg-class,也支援 el-icon-x element-ui 的 icon
  noCache: true // 如果設定為true,則不會被 <keep-alive> 快取(預設 false)
  breadcrumb: false //  如果設定為false,則不會在breadcrumb麵包屑中顯示(預設 true)
  affix: true // 如果設定為true,它則會固定在tags-view中(預設 false)

  // 當路由設定了該屬性,則會高亮相對應的側邊欄。
  // 這在某些場景非常有用,比如:一個文章的列表頁路由為:/article/list
  // 點選文章進入文章詳情頁,這時候路由為/article/1,但你想在側邊欄高亮文章列表的路由,就可以進行如下設定
  activeMenu: '/article/list'
}

示例:

{
  path: '/permission',
  component: Layout,
  redirect: '/permission/index', //重定向地址,在麵包屑中點選會重定向去的地址
  hidden: true, // 不在側邊欄顯示
  alwaysShow: true, //一直顯示根路由
  meta: { roles: ['admin','editor'] }, //你可以在根路由設定許可權,這樣它下面所有的子路由都繼承了這個許可權
  children: [{
    path: 'index',
    component: ()=>import('permission/index'),
    name: 'permission',
    meta: {
      title: 'permission',
      icon: 'lock', //圖示
      roles: ['admin','editor'], //或者你可以給每一個子路由設定自己的許可權
      noCache: true // 不會被 <keep-alive> 快取
    }
  }]
}

路由

這裡的路由分為兩種,constantRoutesasyncRoutes

constantRoutes:代表那些不需要動態判斷許可權的路由,如登入頁、404、等通用頁面

asyncRoutes:代表那些需要動態判斷許可權並通過addRoutes動態新增的頁面

使用permission.js動態判斷許可權並新增路由:

import router, { asyncRoutes, constantRoutes,resetRouter } from '@/router'
/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}
/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })
  return res
}
const state = {
  routes: [],
  addRoutes: []
}
const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}
const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  },
  async changeRoles({  dispatch }, roles) {
    resetRouter()
    // generate accessible routes map based on roles
    const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
    // dynamically add accessible routes
    router.addRoutes(accessRoutes)
  }
}
export default {
  namespaced: true,
  state,
  mutations,
  actions
}

多級目錄(巢狀路由)

如果你的路由是多級目錄,如本專案@/views/nested那樣,有三級路由巢狀的情況下,不要忘記還要手動在二級目錄的根檔案下新增一個

<template>
  <div>
    <!-- xxx html 內容  -->
    <router-view />
  </div>
</template>

原則上有多少級路由巢狀就需要多少個

0

點選側邊欄重新整理當前路由

在用 spa(單頁面應用) 這種開發模式之前,使用者每次點選側邊欄都會重新請求這個頁面,使用者漸漸養成了點選側邊欄當前路由來重新整理 view 的習慣。但現在 spa 就不一樣了,使用者點選當前高亮的路由並不會重新整理 view,因為 vue-router 會攔截你的路由,它判斷你的 url 並沒有任何變化,所以它不會觸發任何鉤子或者是 view 的變化。issue地址,社群也對該問題展開了激烈討論。

方法也很簡單,通過不斷改變 url 的 query 來觸發 view 的變化。我們監聽側邊欄每個 link 的 click 事件,每次點選都給 router push 一個不一樣的 query 來確保會重新重新整理 view。

clickLink(path) {
  this.$router.push({
    path,
    query: {
      t: +new Date() //保證每次點選路由的query項都是不一樣的,確保會重新重新整理view
    }
  })
}

PS:不要忘了在加上一個特定唯一的key,如,但這也有一個弊端就是url後面有一個很難看的query字尾如:xxx.com/article/list?t=1496832345025

側邊欄 外鏈

你也可以在側邊欄中配置一個外鏈,只要你在path中填寫了合法的 url 路徑,當你點選側邊欄的時候就會幫你新開這個頁面。

例如:

{
  "path": "external-link",
  "component": Layout,
  "children": [
    {
      "path": "https://github.com/PanJiaChen/vue-element-admin",
      "meta": { "title": "externalLink", "icon": "link" }
    }
  ]
}

許可權

指令許可權

封裝來一個指令許可權,能簡單快速的實現按鈕級別的許可權判斷。v-permission

使用:

<template>
  <!-- Admin can see this -->
  <el-tag v-permission="['admin']">admin</el-tag>

  <!-- Editor can see this -->
  <el-tag v-permission="['editor']">editor</el-tag>

  <!-- Editor can see this -->
  <el-tag v-permission="['admin','editor']">Both admin or editor can see this</el-tag>
</template>

<script>
// 當然你也可以為了方便使用,將它註冊到全域性
import permission from '@/directive/permission/index.js' // 許可權判斷指令
export default{
  directives: { permission }
}
</script>

對應的檔案:

index.js:

import permission from './permission'

const install = function(Vue) {
  Vue.directive('permission', permission)
}

if (window.Vue) {
  window['permission'] = permission
  Vue.use(install); // eslint-disable-line
}

permission.install = install
export default permission

permission.js:

import store from '@/store'

function checkPermission(el, binding) {
  const { value } = binding
  const roles = store.getters && store.getters.roles

  if (value && value instanceof Array) {
    if (value.length > 0) {
      const permissionRoles = value

      const hasPermission = roles.some(role => {
        return permissionRoles.includes(role)
      })

      if (!hasPermission) {
        el.parentNode && el.parentNode.removeChild(el)
      }
    }
  } else {
    throw new Error(`need roles! Like v-permission="['admin','editor']"`)
  }
}

export default {
  inserted(el, binding) {
    checkPermission(el, binding)
  },
  update(el, binding) {
    checkPermission(el, binding)
  }
}