内容简介:背景: 公司打算做一个(cms),最开始前端参照使用的是Vue+Element的后台管理模板思路参考了一下文章
背景: 公司打算做一个(cms),最开始前端参照 vue-element-admin 的思路,验证了前端鉴权的可能性,大佬写的代码思路清奇,值得学习,后来考虑诸多因素,接口安全性 前端鉴权的难度 以及项目的复杂度,最后选择采用后端渲染动态路由的形式
使用的是Vue+Element的后台管理模板 github
思路参考了一下文章
Vue 动态路由的实现(后台传递路由,前端拿到并生成侧边栏)
实现思路
基础的一些思路和Vue 动态路由的实现 Vue 动态路由的实现(后台传递路由,前端拿到并生成侧边栏) 一样,核心部分加入了自己的理解
getRouter getRouter getRouter
以下为具体实现思路
配置基础路由
基础路由为不登录也可以访问的路由
const StaricRouterMap = [ { path: '/login', component: login, hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', name: 'dashboard', hidden: true, meta: { title: '根目录' }, children: [ { path: 'dashboard', component: () => import('@/views/dashboard/index') } ] }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '*', redirect: '/404', hidden: true }, // .... ] export default new Router({ mode: 'history', // 后端支持可开 scrollBehavior: () => ({ y: 0 }), routes: StaricRouterMap }) 复制代码
与后端同学定制路由结构 (以下为json)
后端会根据当前用户权限动态返回路由结构 前端不再需要考虑权限问题
[{ "id": 1, "name": "Nested", "code": null, "description": null, "url": "/nested", "generatemenu": 0, "sort": 0, "parentId": null, "permName": null, "redirect": "/nested/menu1", "title": "Nested", "icon": "nested", "children": [{ "id": 2, "name": "Menu1", "code": null, "description": null, "url": "menu1", "generatemenu": 0, "sort": 0, "parentId": 1, "permName": null, "redirect": "", "title": "Menu1", "icon": "menu1", "children": [{ "id": 4, "name": "Menu1-1", "code": null, "description": null, "url": "menu1-1", "generatemenu": 0, "sort": 0, "parentId": 2, "permName": null, "redirect": "", "title": "Menu1-1", "icon": "", "children": null }, { "id": 5, "name": "Menu1-2", "code": null, "description": null, "url": "menu1-2", "generatemenu": 0, "sort": 0, "parentId": 2, "permName": null, "redirect": "", "title": "Menu1-2", "icon": "", "children": null }] }, { "id": 3, "name": "Menu2", "code": null, "description": null, "url": "menu2", "generatemenu": 0, "sort": 0, "parentId": 1, "permName": null, "redirect": "", "title": "Menu2", "icon": "menu2", "children": null }] }] 复制代码
解析后端初始路由数据为可用数据
当然这不是直接用于渲染路由 我们需要进行递归处理成为我们想要的数据
../router/_import
export default file => { return map[file] || null } const map = { Nested: () => import('@/views/layout/Layout'), Menu1: () => import('@/views/nested/menu1/index'), 'Menu1-1': () => import('@/views/nested/menu1/menu1-1'), 'Menu1-2': () => import('@/views/nested/menu1/menu1-2') } 复制代码
处理后端原始路由数据
../utils/addRouter
import _import from '../router/_import'// 获取组件的方法 function addRouter(routerlist) { routerlist.forEach(e => { // 删除无用属性 delete e.code delete e.sort delete e.generatemenu delete e.description delete e.permName delete e.id delete e.parentId e.path = e.url delete e.url e.component = _import(e.name) // 动态匹配组件 if (e.redirect === '') { delete e.redirect } if (e.icon !== '' && e.title !== '') { // 配置 菜单标题 与 图标 e.meta = { title: e.title, icon: e.icon } } if (e.title !== '' && e.icon === '') { e.meta = { title: e.title } } delete e.icon delete e.title if (e.children != null) { // 存在子路由就递归 addRouter(e.children) } }) return routerlist } export { addRouter } 复制代码
处理后的路由
我们处理后的路由后面需要与现有的router进行拼接,这里需要根据需求 修改处理路由的规则
[{ "name": "Nested", "redirect": "/nested/menu1", "children": [{ "name": "Menu1", "children": [{ "name": "Menu1-1", "children": null, "path": "menu1-1", "meta": { "title": "Menu1-1" } }, { "name": "Menu1-2", "children": null, "path": "menu1-2", "meta": { "title": "Menu1-2" } }], "path": "menu1", "meta": { "title": "Menu1", "icon": "menu1" } }, { "name": "Menu2", "children": null, "path": "menu2", "component": null, "meta": { "title": "Menu2", "icon": "menu2" } }], "path": "/nested", "meta": { "title": "Nested", "icon": "nested" } }] 复制代码
(核心)合并路由
以上的都是准备工作,就是为了将 初始路由
与后端返回的 动态路由
进行拼接
这里也是最复杂的一块,参考了一些别人的思路,后来完成了这个版本,这就是最上面 实现思路
的代码
import router from './router' import store from './store' import NProgress from 'nprogress' // Progress 进度条 import 'nprogress/nprogress.css' // Progress 进度条样式 import { Message } from 'element-ui' import { addRouter } from './utils/addRouter' var getRouter router.beforeEach((to, from, next) => { NProgress.start() // 进度条 if (localStorage.getItem('login_static') === '1') { if (to.path === '/login') { Message('您已登录,如需切换用户请退出重新登录') next({ path: '/' }) } if (!getRouter) { if (getRouterList('router')) { // 路由信息存在 说明请求阶段以及完成 直接解析路由信息 getRouter = getRouterList('router') // 拿到路由 gotoRouter(to, next) } else { // localStorage不存在路由信息 这需要 请求路由信息 并解析路由 setRouterList(to, next) // 存储路由到localStorage } } else { // getRouter变量存在 说明路由信息存在 直接通过 next() } } else { if (to.path === '/login') { next() } else { next(`/login`) } } }) router.afterEach(() => { NProgress.done() // 结束Progress }) function gotoRouter(to, next) { try { getRouter = addRouter(getRouter) router.addRoutes(getRouter) // 动态添加路由 global.antRouter = router.options.routes.concat(getRouter) // 将路由数据传递给全局变量,做侧边栏菜单渲染工作 next({ to, replace: true }) } catch (error) { localStorage.setItem('login_static', 0) } } function setRouterList(to, next) { store.dispatch('getRouter').then(asyncRouter => { // 请求路由数据 localStorage.setItem('router', JSON.stringify(asyncRouter)) getRouter = getRouterList('router') // 拿到路由 gotoRouter(to, next) }) } function getRouterList(name) { return JSON.parse(localStorage.getItem(name)) } 复制代码
修改侧边栏的应用路由地址
需要注意的是 通过 addRoutes合并的路由 不会被 this.$router.options.routes
获取到,所以需要将获取的路由拼接到 this.$router.options.routes
上
最后修改渲染侧边栏部分部分的代码
src\views\layout\components\Sidebar\index.vue
computed: { // .... routes() { return global.antRouter // 这里应该最好使用vuex的全局变量 }, // .... } 复制代码
这样就实现了动态渲染后端传递的路由,,感觉还是用可以优化的地方,欢迎指正
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- React服务端渲染(前后端路由同构)
- vue路由篇(动态路由、路由嵌套)
- 小程序封装路由文件和路由方法,5种路由方法全解析
- Octane渲染入门-渲染设置图文版
- Vue的路由及路由钩子函数
- gin 源码阅读(二)-- 路由和路由组
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Google是如何控制世界的
(美)丹尼尔·伊克比亚 / 李军 / 东方出版社 / 2008-08 / 36.00元
秘Google的发展之路! Google,这个有着数百亿的网页存储量、每天两亿搜索次数的搜索引擎,最初仅仅是一个方程式。这个由拉里·佩奇和塞吉·布林两位天才创造出的超级算法甚至比可口可乐的配方还要保密。 当广告公司为自己网页在搜索结果中的排序争得头破血流时,Google正悠然地坐收渔翁之利,这种天才的拍卖广告链接的商业模式给Google带来了令人瞠目结舌的企业利润!仅仅从1999~20......一起来看看 《Google是如何控制世界的》 这本书的介绍吧!