1、前言
上篇,我們講了后端的授權。與后端不同,前端主要是通過功能入口如菜單、按鈕的顯隱來控制授權的。具體來講,就是根據指定用戶的制定權限來加載對應側邊欄菜單和頁面內的功能按鈕。我們一個個來講。
2、側邊欄菜單
鑒於本項目使用了vue-router,那顯然,側邊欄就會跟對應路由關聯,同時,前端項目會注冊路由導航事件,此事件見src根目錄下permission.js:
截圖中,上邊的紅框代表是在注冊路由跳轉前回調鈎子,此鈎子可以根據具體情況決定是否需要導航到目的路由或導航到其他路由。下邊的紅框先調用menu store中的獲取側邊欄action,從后端拿到本用戶具有權限的側邊欄菜單:
從后端拿到側邊欄菜單json,前端是沒辦法直接使用的,一堆json對象或者字符串,與Vue路由、視圖並沒法兒無縫銜接,所以上邊我們看到調用了travseRoutes方法,此方法在前端工具類route.js中,如下:
主要用意就是經由后端動態菜單配置前端vue-router動態路由,用到了vue-router中路由懶加載這個重要的特性。以上就是前端動態側邊欄的實現。
3、功能按鈕
大部分項目都做到了菜單級的權限控制,但做到頁面級別的,倒是不多。畢竟他該多,而且也是要費點兒功夫的。那這里我們就來看看前端是如何實現按鈕級權限控制的。
一般而言,組件顯隱可以通過v-show或v-if,但若通過這種方式,恐怕得在viewmodel中定義大量屬性,最好的情況,也得在需要控制的地方頂一個計算屬性吧,這種方式恐怕代價還是有一些的。針對這點,web-flash前端項目中,很巧妙地用到了自定義Vue指令這個特性,將按鈕的加載與去除邏輯封裝了起來,具體在前端項目src/directive/permission.js中:
import store from '@/store' export default{ inserted(el, binding, vnode) { const { value } = binding const permissions = store.getters && store.getters.permissions if (value && value instanceof Array && value.length > 0) { const permissionRoles = value const hasPermission = permissions.some(permission => { return permissionRoles.includes(permission) }) if (!hasPermission) { el.parentNode && el.parentNode.removeChild(el) } } else { throw new Error(`need roles! Like v-permission="['admin','editor']"`) } } }
自定義指令有幾種類型鈎子函數,這里選取了inserted,代表是在元素插入后判斷有無指定按鈕權限,如果沒有,則從界面再移除。接下來,我們就實際看看效果。首先,在用戶管理對應的視圖js中引入自定義指令:
然后,我們在用戶視圖文件中對新增、編輯、刪除用戶幾個按鈕用自定義指令做權限控制:
<el-col :span="24"> <el-button type="success" size="mini" icon="el-icon-plus" @click.native="add" v-permission="['/mgr/add']"> {{$t('button.add') }} </el-button> <el-button type="primary" size="mini" icon="el-icon-edit" @click.native="edit" v-permission="['/mgr/edit']"> {{$t('button.edit') }} </el-button> <el-button type="danger" size="mini" icon="el-icon-delete" @click.native="remove" v-permission="['/mgr/delete']"> {{$t('button.delete') }} </el-button> <el-button type="info" size="mini" icon="el-icon-role" @click.native="openRole">角色分配</el-button> </el-col> </el-row>
之后,我們用一個不具有用增刪改權限的用戶登錄系統:
可以看到,添加、修改、刪除用戶菜單是不可見的。那現在我把添加按鈕的v-permission指令拿掉,則再看效果:
可見,拿掉v-perission,添加用戶按鈕顯示出來了,反面說明前端授權生效了。