后台管理动态权限配置思路-笔记

视频地址: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数组里的数字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zwfXwMTU-1609927054432)(C:\Users\ADMINI~1\AppData\Local\Temp\WeChat Files\b03bd4333b09e9e3fbab7fa4d7a717b.png)]

// 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 方法,返回路由对象
  1. 渲染真正的路由上 这里还把方法写到 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 />
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值