後臺管理動態許可權配置思路-筆記
阿新 • • 發佈:2021-01-07
視訊地址:https://www.bilibili.com/video/BV11A411J7z5
1.後端返回路由的思路
1. 登入後,後端返回路由許可權api列表JSON
2. 處理後端返回的JSON,轉化成Vue的路由結構
3. 將靜態路由結構轉化成動態路由
4. 最後動態渲染選單元件
2.前後端可以這樣定義路由規則
module.exports = [
{
id: 2, // 第一層是 home,就不寫了
pid: 0, // pid是零,證明他是沒有父級的,他是第一層路由
path: '/course', // 路徑
name: 'Course', // 元件名稱
title: '課程管理' // 名子
},
{
id: 3,
pid: 2, // pid是二,證明他是有父級的,他是id為2的子路由
path: 'operate', // 路徑
name: 'CourseOperate', // 元件名稱
title: '課程操作', // 名子
link: '/course/operate' // 點選時候的子路由
},
{
id: 4,
pid: 3, // pid是三,證明他是有父級的,他是id為3的子路由
path: 'info_data', // 路徑
name: 'CourseInfodata', // 元件名稱
title: '課程資料', // 名子
link: '/course/operate/info_data' // 點選時候的子路由
},
{
id: 5,
pid: 2, // pid是二,證明他是有父級的,他是id為2的子路由
path: 'add', // 路徑
name: 'CourseAdd', // 元件名稱
title: '增加課程', // 名子
link: '/course/add' // 點選時候的子路由
},
{
id: 6, // 第一層是 home,就不寫了
pid: 0, // pid是零,證明他是沒有父級的,他是第一層路由
path: '/student', // 路徑
name: 'Student', // 元件名稱
title: '學生管理' // 名子
},
{
id: 7,
pid: 6, // pid是二,證明他是有父級的,他是id為6的子路由
path: 'operate', // 路徑
name: 'Student/Operate', // 元件名稱
title: '學生操作', // 名子
link: '/Student/Operat' // 點選時候的子路由
},
{
id: 8,
pid: 6, // pid是二,證明他是有父級的,他是id為6的子路由
path: 'add', // 路徑
name: 'StudentAdd', // 元件名稱
title: '增加學生', // 名子
link: '/Student/add' // 點選時候的子路由
}
]
3.面試官問後臺管理許可權的路由思路
一些中小型的公司的路由許可權可能是這樣做的,先把所有的路由寫好,靜態的放在路由表的裡面做一個變數,然後從後端請求回資料以後,再去對比這張靜態表,然後再刪減,最後再合併到原本的路由當中去,實際上這樣做是不對的。
真正的路由應該從後端的表裡面直接取出來,然後返回給前端,前端根據定義的規則形成樹(路由樹),然後轉成路由,最後再渲染到真正的路由上。
4.後端返回 api , 解析 看得到的 初級,中級,高階路由的許可權(品好下走)
// id :1 許可權等級
// 等級的稱呼 沒多大作用 過
// auth 裡面的數字,就是當前等級能看到的路由許可權,對應的是上面路由表裡的id,往上翻,看明白了再回來
module.exports = [
{
id: 1, // 普通人的許可權,只能看到auth裡面的幾個路由,細品,你細品再往下看
name: 'zhangsan',
auth:[2,3,4,7] // 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
},
{
id: 2, // 小老闆的許可權,只能看到auth裡面的幾個路由,細品,你細品再往下看
name: 'lisi',
auth:[2,3,5,6,7,8] // 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
},
{
id: 3, // 大老闆的許可權,能看到所有的路由,細品,你細品再往下看
name: 'wangwu',
auth:[2,3,4,5,6,7,8] // 這裡的數字就是上面路由表裡定義的id號,你細品,多品幾遍想通再往下走
},
]
5.接下來的步驟還是後端處理,大概思路就是,根據登入使用者的等級,對應相應auth裡面的數字 id , 迴圈 , 與上上面定義路由表裡的id對比,有相同的就返回給前端(這裡是後端的思路,前端了解最好,工作了可以跟後端***)
6.再下面就到前端了,開始幹活吧
// 1.前端請求資料,引數假設是 uid,其實就是使用者的等級,把這個等級傳給後端,後端判斷當前等級返回對應的許可權,就是上面的 auth 裡面的路由id, 只要有的,從之前定義的路由表裡拿出來,全部返回給前端就行了,剩餘的交給前端形成樹,這個請求是使用者一登入就得請求的,前端可以把它放在App.vue 裡面請求( 趕緊複習下 vuex )
// 2.呼叫第一步介面,uid好比傳的3,返回的資料如下圖,不明白的話可以看一下id 為3物件下面auth數組裡的數字
// 3. 轉樹,轉成vue的路由樹,根據的是前後端共同定義的規則,忘了看第二大步(上面上面),這裡要用vuex了
// state 檔案
export default { // 裡面三個預設
uid: 2, // 預設使用者的等級
hasAuth: false, // 預設沒有許可權
userRouters:[] // 樹形結構的資料,預設為空
}
// actions 檔案 請求非同步處理的地方
import { getUserRouters } from '../services'; // 這裡是引用的axios的介面
import { formatRouterTree } from '../libs/utils'; // 結構化的封裝方法
export default {
async setUserRouters({ commit, state }) { // async await 不會的話自己百度
const userRouters = await getUserRouters(state.uid); // 拿到返回的路由陣列,就是上面的圖
// 拿到返回樹形結構化,可以列印看一下
// 這裡把結構化的封裝方法寫外面了
payload = formatRouterTree(userRouters) // 呼叫封裝方法
console.log( payload ) // 列印檢視樹結構是否符合
// 下面通過 mutations 把結構化後的樹存到state裡面
commit('setUserRouters', payload ); // 把樹結構傳過去,放到state裡的 userRouters
commit('setAuth', true); // 改變 state 裡的 hasAuth ,此時就有許可權了
}
// 在 main.js裡面執行上面這個方法
// import store from './stort' 有的就不用加了,沒有的別忘了引入
// store.dispatch('setUserRouters')
}
// mutations.js 檔案
export default {
setAuth (state, auth) {
state.hasAuth = auth;
},
setUserRouters (state, userRouters) {
state.userRouters = userRouters;
}
}
// 完事做路由了
// libs/utils.js 檔案
function formatRouterTree (data) { // data 就是傳過來的路由物件,如上圖,在這裡結構化
//
let parents = data.filter(p => pid === 0) // 拿到所有的一級路由
let children = data.filter(c => pid !== 0) // 拿到非一級路由的所有路由
dataToTree(parents, children); // 每次遞迴一下
//
function dataToTree (parents, children) {
parents.map((p) => { // 遍歷父親,拿出每一項
children.map((c, i) => { // 遍歷兒子裡面的pid是不是等於父親的id
if (c.pid === p.id) { // 證明這個c 是 p 的兒子
let _c = JSON.parse(JSON.stringify(children)); // 深拷貝
_c.spllice(i,1); // 留下真正的自己
dataToTree([c], _c) // 再呼叫一遍
if (p.children) {
p.children.push(c);
} else {
p.children = [c];
}
}
})
})
}
return parents; // 返回
}
export { formatRouterTree }
// main.js 檔案
import store from './stort' // 有的就不用加了,沒有的別忘了引入
store.dispatch('setUserRouters') // 呼叫actions 方法,返回路由物件
- 渲染真正的路由上 這裡還把方法寫到 utils.js 裡
// libs/utils.js 檔案
function formatRouterTree (data) { // data 就是傳過來的路由物件,如上圖,在這裡結構化
//
let parents = data.filter(p => pid === 0) // 拿到所有的一級路由
let children = data.filter(c => pid !== 0) // 拿到非一級路由的所有路由
dataToTree(parents, children); // 每次遞迴一下
//
function dataToTree (parents, children) {
parents.map((p) => { // 遍歷父親,拿出每一項
children.map((c, i) => { // 遍歷兒子裡面的pid是不是等於父親的id
if (c.pid === p.id) { // 證明這個c 是 p 的兒子
let _c = JSON.parse(JSON.stringify(children)); // 深拷貝
_c.spllice(i,1); // 留下真正的自己
dataToTree([c], _c) // 再呼叫一遍
if (p.children) {
p.children.push(c);
} else {
p.children = [c];
}
}
})
})
}
return parents; // 返回
}
function generateRouter (userRouters) { // 真正的路由
let newRouters = userRouters.map((r) => {
let routes = {
path: r.path,
name: r.name,
component: () => import(`@/views/${r.name}`)
}
if (r.children) { // 如果有子路由
routers.children = generateRouter(r.children);
}
return routes;
})
return newRouters; // 最終路由
}
export { formatRouterTree, generateRouter }
8.main.js
// main.js 檔案
import store from './stort' // 有的就不用加了,沒有的別忘了引入
import { generateRouter } from '@/libs/utils' // 引入路由樹
router.beforEach(async (to, form, next) => {
if (!store.state.hasAuth) { // 判斷有沒有許可權
await store.dispatch('setUserRouters'); // 呼叫actions 方法,返回路由物件
const newRouters = generateRouter(store.state.userRouters);
router.addRoutes(newRoutes);
next({path: to.path})
} else { // 如果有許可權
next();
}
})
9.完畢建立頁面,檢視效果
// 檢視所有路由,建立頁面 有子路由的記得加 <router-view />