vue后台管理之动态加载路由的方法
在这里我们将会实现一个vue动态路由的案列,当用户登陆成功后,根据用户的角色,拿到他对应的菜单信息,并将它动态的载入到我们的路由中。
我们的通用的后台管理系统中,我们会根据权限的粗细不同,会对每个角色每个权限每个资源进行控制。同样的我们也需要实现一个这样的功能。 这篇文章我将主要讲vue端的实现,关于后台接口我就不会涉及,当我接触的时候我们的后台接口是springcloud实现。
一、思路
在vue-router对象中初始化公共路由,比如(404,login)等,然后在用户登陆成功,根据用户的角色信息,获取对应权限菜单信息menuList,并将后台返回的menuList转换成我们需要的router数据结构,然后通过vue-router2.2新添的router.addRouter(routes)方法,我们可以将转后的路由信息保存于vuex,这样我们可以在我们的SideBar组件中获取我们的全部路由信息,并且渲染我们的左侧菜单栏,让动态路由实现。
二、实现
1、公共路由定义
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) / Layout / import Layout from '../views/layout/Layout' export const constantRouterMap = [ { path: '/login', ponent: () => import('@/views/login/index'), hidden: true }, { path: '/404', ponent: () => import('@/views/404'), hidden: true }, { path: '/', ponent: Layout, redirect: '/dashboard', name: 'Dashboard', hidden: true, children: [{ path: 'dashboard', ponent: () => import('@/views/dashboard/index') }] }, ] export default new Router({ scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap })
2、获取菜单信息
router.beforeEach((to, from, next) => { NProgress.start() // start progress bar if (getToken()) { // determine if there has token / has token/ if (to.path === '/login') { next({ path: '/' }) NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it } else { if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息 store.dispatch('GetInfo').then(res => { // 拉取user_info const roles = res.roles store.dispatch("GetMenu").then(data => { initMenu(router, data); }); next() }).catch((err) => { store.dispatch('FedLogOut').then(() => { Message.error(err || 'Verification failed, please login again') next({ path: '/' }) }) }) } else { next() } } } else { / has no token/ if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 next() } else { next('/login') // 否则全部重定向到登录页 NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it } } }) router.afterEach(() => { NProgress.done() // finish progress bar })
在这里 我们通过在router的beforeEach钩子函数 判断用户是否已经获得角色信息,如果没有,则请求后台获取对应的角色信息,然后通过角色信息请求获取对应的菜单列表,获取到菜单列表,然后去格式化菜单列表,使其转换成router数组的结构。
3、动态加载路由
import store from '../store' export const initMenu = (router, menu) => { if (menu.length === 0) { return } let menus = formatRoutes(menu); // 添加 let unfound = { path: '', redirect: '/404', hidden: true } menus.push(unfound) router.addRoutes(menus) store.mit('ADD_ROUTERS',menus) } export const formatRoutes = (aMenu) => { const aRouter = [] aMenu.forEach(oMenu => { const { path, ponent, name, icon, childrens } = oMenu if (!validatenull(ponent)) { let filePath; const oRouter = { path: path, ponent(resolve) { let ponentPath = '' if (ponent === 'Layout') { require(['../views/layout/Layout'], resolve) return } else { ponentPath = ponent } require([`../${ponentPath}.vue`], resolve) }, name: name, icon: icon, children: validatenull(childrens) ? [] : formatRoutes(childrens) } aRouter.push(oRouter) } }) return aRouter }
在这里我们把menList转换成routerList因为我们后台返回的数据不是规范的router结构,所以这里需要我们处理一下,如果你们后台返回规范的就不需要处理,然后通过router.addRoutes把后台返回的加入到我们的路由中,并且将其保存在我们的vuex中,需要主要的 如果404组件一定要放在动态路由在后载入。
4、渲染菜单
其实这里已经不属于我们的所讲的重点,在这里只需要取出上一步存在vuex中的路由信息,并且将其渲染成我们的左侧菜单栏就可以。在这里我们使用了element-ui。
<template> <el-scrollbar wrapClass="scrollbar-wrapper"> <el-menu mode="vertical" :show-timeout="200" :default-active="$route.path" :collapse="isCollapse" background-color="#304156" text-color="#bfcbd9" active-text-color="#409EFF" > <sidebar-item v-for="route in permission_routers" :key="route.name" :item="route" :base-path="route.path"></sidebar-item> </el-menu> </el-scrollbar> </template> <script> import { mapGetters } from 'vuex' import SidebarItem from './SidebarItem' import { validatenull } from "@/utils/validate"; import { initMenu } from "@/utils/util"; export default { ponents: { SidebarItem }, created() { }, puted: { ...mapGetters([ 'permission_routers', 'sidebar', 'addRouters' ]), isCollapse() { return !this.sidebar.opened } } } </script>
就这样我们动态加载路由就是实现了,是不是很简单,关键点就是router.addRoute方法。狼蚁网站SEO优化我就说一下防踩坑点。
三、防坑
1、关于加载菜单信息的时机
在此之前我将第二步获取菜单信息放在我的SideBar组件的create函数中,当时我发现也没有什么问题。登录跳转到home界面 左侧菜单也成功渲染,点击菜单进入我们动态加载的路由界面,也没问题。当我点击刷新的时候问题来。页面空白 控制台也不报错。当时我就蒙蔽了,什么情况,不是好好的嘛?如果大家也遇到这种这时候大家不要着急,冷静的分析整个流程,就会发现问题的所在。
1、登陆成功跳转home界面,home组件是公共路由,存在的没问题。
2、这时候 sidebar组件create钩子触发,成功获取菜单列表
3、菜单列表转成路由数组,并且加载到router实例中和vuex中
4、sidebar从vuex获取到路由数组渲染菜单 进入我们动态加载页面中,显示正常,这一切看起来没什么问题
5、点击浏览器的刷新按钮、或者F5,页面空白。
原因 第五步中我们我们浏览器刷新,在spa应用整个vue实例会重新加载,也是说我的vue-router会重新初始化,那么我们之前的动态addRoute就不存在了,我们此时访问一个不存在的页面,所以我们的sidebar组件也就不会被访问,那么也无法获取菜单信息,就导致页面空白。所以我们需要把加载菜单信息这一步放在router的全局守卫beforeEach中就可以了。
2、关于404组件的位置
大家可以看到
export const initMenu = (router, menu) => { if (menu.length === 0) { return } let menus = formatRoutes(menu); // 添加 let unfound = { path: '', redirect: '/404', hidden: true } menus.push(unfound) router.addRoutes(menus) store.mit('ADD_ROUTERS',menus) }
我强调了 404组件一定要放在动态路由组件的,不然你刷新动态加载的页面,会跳转到404页面的。
四、效果图
动态路由
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持狼蚁SEO。
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程