很多时候我们在项目的路由都是在前端配置好的
但是有的时候为了进行全面的权限控制,会需要后台给出路由表,前端再渲染。不用在前端配置。
下面主要讲一下思路
1、和后台小哥哥沟通好数据,把我们前端配置的路由表数据给他,他就能看懂了
2、拿到数据需要我们自己再处理,我们路由的处理放在路由守卫,Router.beforeEach里面做,但是路由中的component后台是给不了的,我这想了两种解决方法
//第一种 可以跟后端小哥约定一个字段,把路由的url后半段直接给后端小哥哥我们直接加载,这里面注意import有时候webpack识别不了所以需要用require加载一下
//componentUrl就是后台给的数据 componentUrl:"view-userControl/UserControl.vue"
return () => import(`@/views/${componentUrl}`);
//第二种 我们写方法按照我们自己的起名规则自己去匹配 我这里直接封装了一个方法
//用来存放特殊路由的url
const routerObj = {
userControl:"view-userControl/UserControl.vue"
}
const pathaqsg = (name,Pname) =>{
let url = ''
if(routerObj[name]){
url = routerObj[name]
}else if(Pname){ //Pname 父级
url = 'view-' + Pname + name.substring(0,1).toUpperCase() + name.substring(1)
}
return resolve => require([`@/views/${url}`],resolve)
}
这样我们就拿到了最重要的数据,即component。
3、把后台提供的数据处理成我们需要的路由表,添加到路由中,我们这里为了方便跟端小哥哥约定字段时就严格按照我们路由的格式来 {path:"",name:"",children:[]},所以我这边直接处理component,然后添加到路由里面
router.addRoutes(路由表)
这里面注意的是像404,403,500 这类共用的报错页面一定要最后加载
4.这样一个动态路由就生成了,这里注意一个小坑,路由表生成后当你退出换一个用户进来后,路由表并不会自动更新,这个情况下会有问题,所以需要我们手动清除路由,有两种方法,第一种:直接刷新页面重置所有变量,第二种:利用路由的matcher方法
const createRouter = ()=>new Router({
routes: routerData,
mode:"history"
})
//写一个重置路由的方法,切换用户,或者退出时清除动态加载的路由
export const router = createRouter()
export function resetRouter(){
const newRouter = createRouter()
router.matcher = newRouter.matcher //新路由的实例matcher,赋值给旧路由实例的matcher,(相当于replaceRouter)
}
思路很简单,这里附上我router.js里面的代码,可以做个参考,(一定要注意路径哦)
import Vue from 'vue'
import Router from 'vue-router'
import Cookies from "js-cookie"
import Login from '@/views/Login'
import NotFound from '@/views/Error/404'
import Home from '@/views/Home'
import Intro from '@/views/Intro/Intro'
import api from '@/http/api'
import store from '@/store'
Vue.use(Router)
let routerData = [
{
path: '/',
name: '首页',
component: Home,
children: [
{
path: '',
name: '系统介绍',
component: Intro,
meta: {
icon: 'fa fa-home fa-lg',
index: 0
}
}
]
},
{
path: '/login',
name: '登录',
component: Login
},
]
const createRouter = ()=>new Router({
routes: routerData,
mode:"history"
})
//写一个重置路由的方法,切换用户,或者退出时清除动态加载的路由
export const router = createRouter()
export function resetRouter(){
const newRouter = createRouter()
router.matcher = newRouter.matcher //新路由的实例matcher,赋值给旧路由实例的matcher,(相当于replaceRouter)
}
router.beforeEach((to, from, next) => {
// 登录界面登录成功之后,会把用户信息保存在会话
// 存在时间为会话生命周期,页面关闭即失效。
let token = Cookies.get('token')
if (to.path === '/login') {
// 如果是访问登录界面,如果用户会话信息存在,代表已登录过,跳转到主页
if (token) {
next({ path: '/' })
} else {
resetRouter()
next()
}
} else {
if (!token) {
// 如果访问非登录界面,且户会话信息不存在,代表未登录,则跳转到登录界面
next({ path: '/login' })
resetRouter()
} else {
// 加载动态菜单和路由
addDynamicMenuAndRoutes(to, from)
next()
}
}
})
/**
* 加载动态菜单和路由
*/
function addDynamicMenuAndRoutes(to, from) {
//使用vuex记录是否已经加载过路由表
if (store.state.app.menuRouteLoaded) {
return
}
//ajax查询路由
api.menu.findNavTree({ 'userName': localStorage.userName })
.then(res => {
// 添加动态路由
let dynamicRoutes = addDynamicRoutes(res.data)
dynamicRoutes = dynamicRoutes.concat([{ //404,403,500 这些报错页面最后加载
path: '/404',
name: 'notFound',
component: NotFound
}])
router.addRoutes(dynamicRoutes)
// 保存加载状态
store.commit('menuRouteLoaded', true)
// 保存菜单树
store.commit('setNavTree', res.data)
console.log('路由加载完成',router)
})
.catch(function (res) {
})
}
/**
* 添加动态(菜单)路由
* @param {*} menuList 菜单列表
* @param {*} routes 递归创建的动态(菜单)路由
*/
function addDynamicRoutes(menuListAll = [], routes = []) {
let menuList = [...menuListAll]
thgjRouter(menuList)
function thgjRouter(arr,p){
for(var i = 0 ; i < arr.length;i++){
arr[i]['component'] = pathaqsg(arr[i].name,p) //使用懒加载的方式自动拼接动态路由
if(arr[i].children && arr[i].children.length > 0){
thgjRouter(arr[i].children,(p?p:'')+arr[i].name+"/")
}
}
}
return menuList
}
//用来存放特殊路由的url
const routerObj = {
userControl:"view-userControl/UserControl.vue"
}
const pathaqsg = (name,Pname) =>{
let url = ''
if(routerObj[name]){
url = routerObj[name]
}else if(Pname){ //Pname 父级
url = 'view-' + Pname + name.substring(0,1).toUpperCase() + name.substring(1)
}else{
url = 'view-' + name + name.substring(0,1).toUpperCase() + name.substring(1)
}
return resolve => require([`@/views/${url}`],resolve)
}
export default router