日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

路由到另外一个页面_一个简单的Vue按钮级权限方案

發布時間:2024/9/18 vue 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 路由到另外一个页面_一个简单的Vue按钮级权限方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在年初開發一個中后臺管理系統,功能涉及到了各個部門(產品、客服、市場等等),在開始的版本中,我和后端配合使用了花褲衩手摸手系列的權限方案,前期非常nice,但是慢慢的隨著功能增多、業務越來越復雜,就變得有些吃力了,因為我們的權限動態性太大了

  • 手摸手系列權限方案是有比較清晰的權限劃分的,而我們公司部門的崗位職責有時比較模糊。
  • 后端采用RBAC權限方案,為了達到第1點要求,將角色劃分的很細,并且角色有時頻繁變動,導致每一次前端都需要手動維護
  • 為了解決上面2個痛點,我將原方案進行了一丟丟改造。

  • 前端不再以角色來控制權限,而是以更小粒度的操作(接口)來控制,也就是前端不關心角色
  • 路由還是由前端維護(我們的后端很排斥維護和他們不相干的東西),但改為通過操作列表對權限路由進行過濾
  • 使用單一的方式(方便維護)控制頁面的局部權限,不再使用自定義指令方式,而是通過函數式組件,原因是使用自定義指令有多余的開銷(插入再移除)
  • 我自己是一名從事了多年開發的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個月整理了一份最適合2019年學習的web前端學習干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關注我并在后臺私信我:前端,即可免費獲取。

    后端的配合:

  • 提供一個獲取當前用戶操作列表的接口
  • 操作列表需要增加一個唯一標識(操作碼)供前端使用,不變的
  • 操作列表需要增加一個routerName字段,用于可視化權限編輯
  • 有一些注意點:

  • 比如一個有權限的列表頁面A,同時這個列表接口被權限頁面B使用,現在你配置權限讓某一個用戶沒有A頁面權限,但可以使用B頁面,如果你的本意是可以使用B頁面的所有功能,這時就會有問題,所以盡量不要將權限接口跨頁面使用,需要分清哪些數據需要通過字典接口獲取還是通過權限接口獲取
  • 有些人可能會糾結,前端維護權限安全嗎?肯定是不安全的,安全性主要還在后端這邊把控,后端做好數據和接口方面的權限控制,前端做權限控制我認為主要還是為了交互體驗等。沒有權限你為什么要讓我看到那一坨?
  • 在使用這種方式之前,要明確當前場景是否確實需要這么做,畢竟在項目比較大且接口很多的情況下,你跟操作碼之間有一場持久戰
  • 實現

    操作列表示例

    以Restful風格接口為例

    路由的變化

    在路由的meta中增加一個配置字段如requireOps,值可能為String或者Array,這表示當前路由頁面要顯示的必要的操作碼,Array類型是為了處理一個路由頁面需要滿足同時存在多個操作權限時才顯示的情況。若值不為這2種則視為無權限控制,任何用戶都能訪問

    由于最終需要根據過濾后的權限路由動態生成菜單,所以還需要在路由選項中增加幾個字段處理顯示問題,其中hidden優先級大于visible

  • hidden,值為true時,路由包括子路由都不會出現在菜單中
  • visible,值為false時,路由不顯示,但顯示子路由
  • 由于路由在前端維護,所以以上配置只能寫死,如果后端能同意維護這一份路由表,那就可以有很多的發揮空間了,體驗也能做的更好。

    權限路由過濾

    先將權限路由規范一下,同時保留一個副本,可能在可視化時需要用到

    獲取到操作列表后,只需要遍歷權限路由,然后查詢requireOps代表的操作有沒有在操作列表中。這里需要處理一下requireOps未設置的情況,如果子路由中都是權限路由,需要為父級路由自動加上requireOps值,不然當所有子路由都沒有權限時,父級路由就被認為是無權限控制且可訪問的;而如果子路由中只要有一個路由無權限控制,那就不需要處理父路由。所以這里可以用遞歸來解決,先處理子路由再處理父路由

    const filterPermissionRoutes = (routes, cb) => {// 可能父路由沒有設置requireOps 需要根據子路由確定父路由的requireOpsroutes.forEach(route => {if (route.children) {route.children = filterPermissionRoutes(route.children, cb)if (!route.meta.requireOps) {const hasNoPermission = route.children.some(child => child.meta.requireOps === null)// 如果子路由中存在不需要權限控制的路由,則跳過if (!hasNoPermission) {route.meta.requireOps = [].concat(...route.children.map(child => child.meta.requireOps))}}}})return cb(routes) }

    然后根據操作列表對權限路由進行過濾

    let operations = null // 從后端獲取后更新它 const hasOp = opcode => operations? operations.some(op => op.opcode === opcode): falseconst proutes = filterPermissionRoutes(permissionRoutes, routes => routes.filter(route => {const requireOps = route.meta.requireOpsif (requireOps) {return requireOps.some(hasOp)}return true }))// 動態添加路由 router.addRoutes(proutes)

    函數式組件控制局部權限

    這個組件實現很簡單,根據傳入的操作碼進行權限判斷,若通過則返回插槽內容,否則返回null。另外,為了統一風格,支持一下root屬性,表示組件的根節點

    const AccessControl = {functional: true,render (h, { data, children }) {const attrs = data.attrs || {}// 如果是root,直接透傳if (attrs.root !== undefined) {return h(attrs.root || 'div', data, children)}if (!attrs.opcode) {return h('span', {style: {color: 'red',fontSize: '30px'}}, '請配置操作碼')}const opcodes = attrs.opcode.split(',')if (opcodes.some(hasOp)) {return children}return null} }

    動態生成權限菜單

    以ElementUI為例,由于動態渲染需要進行遞歸,如果以文件組件的形式會多一層根組件,所以這里直接用render function簡單寫一個示例,可以根據自己的需求改造

    // 權限菜單組件 export const PermissionMenuTree = {name: 'MenuTree',props: {routes: {type: Array,required: true},collapse: Boolean},render (h) {const createMenuTree = (routes, parentPath = '') => routes.map(route => {// hidden: 為true時當前菜單和子菜單都不顯示if (route.hidden === true) {return null}// 子路徑處理const fullPath = route.path.charAt(0) === '/' ? route.path : `${parentPath}/${route.path}`// visible: 為false時不顯示當前菜單,但顯示子菜單if (route.visible === false) {return createMenuTree(route.children, fullPath)}const title = route.meta.titleconst props = {index: fullPath,key: route.path}if (!route.children || route.children.length === 0) {return h('el-menu-item',{ props },[h('span', title)])}return h('el-submenu',{ props },[h('span', { slot: 'title' }, title),...createMenuTree(route.children, fullPath)])})return h('el-menu',{props: {collapse: this.collapse,router: true,defaultActive: this.$route.path}},createMenuTree(this.routes))} }

    接口的權限控制

    我們一般用axios,這里只需要在axios封裝的基礎上加幾行代碼就可以了,axios封裝花樣多多,這里簡單示例

    const ajax = axios.create(/* config */)export default {post (url, data, opcode, config = {}) {if (opcode && !hasOp(opcode)) {return Promise.reject(new Error('沒有操作權限'))}return ajax.post(url, data, { /* config */ ...config }).then(({ data }) => data)},// ... }

    到這里,這個方案差不多就完成了,權限配置的可視化可以根據操作列表中的routeName來做,將操作與權限路由一一對應,在demo中有一個簡單實現

    原文鏈接:https://juejin.im/post/5dd2a8d1518825499543c772
    作者:前端小智

    總結

    以上是生活随笔為你收集整理的路由到另外一个页面_一个简单的Vue按钮级权限方案的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。