element-admin的側邊欄導航和許可權
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> 快取 } }] }
路由
這裡的路由分為兩種,constantRoutes和asyncRoutes
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>
原則上有多少級路由巢狀就需要多少個
點選側邊欄重新整理當前路由
在用 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)
}
}