解决vue-router addRoutes路由不刷新问题

简介: 在vue后台管理项目中,动态路由是一个必须的功能,根据不同权限显示不同的路由表。通常的做法有两种,1)前端将所有路由定义到配置文件中,后台返回用户角色。

1.发现问题

      在vue后台管理项目中,动态路由是一个必须的功能,根据不同权限显示不同的路由表。通常的做法有两种,1)前端将所有路由定义到配置文件中,后台返回用户角色。前端根据用户角色从配置文件中去相应的路由对象生成路由表。(此种方法用的比较多,至今未发现有何问题). 2)前端路由表中只配置公共路由,后台根据前端登录用户返回相应的路由表。前端拿到路由表动态(addRoutes)的加载出来。正常登录没啥问题,登录成功后页面跳转也可以,但是在动态添加的路由部分刷新页面会出现404问题。

router.beforeEach((to, from, next) => {  
if (from.query.code || to.query.code ) {    
   let time = (new Date()).valueOf()    
   localStorage.setItem('EXPIRE-TIME', time) 
 }   
  isLogin(to, from, next)
})
router.afterEach(() => {})
//判断是否需要跳转到登录页
function isLogin(to, from, next) {  
     if (JSON.parse(localStorage.getItem('IS_LOGIN'))) {    ...... 
      } else if (!JSON.parse(localStorage.getItem('IS_LOGIN'))) {    
// 在免登录白名单,直接进入    
       if (whiteList.indexOf(to.path) !== -1 || to.path.search(/(^\/i\/[a-z0-9A-Z]+$)/g) > -1) {
        next()    
       } else { 
           if(to.path == '/'){        queryUserInfo(next)      
           }else{        next('/user/login')      
           }    
         }  }}
//在登录之后,进入首页之前进行信息获取,与是否登录验证
function  queryUserInfo(next) {    
   let url = `${process.env.VUE_APP_URL}/userprofile`    
   axios.get(url).then((res) => {
            if (res.data.success) {
                 ......
                //初始化页面数据
                if(routeTable && routeTable.length > 0){
                  addRoutes(routeTable)
                  next()
                }else{
                  //从后台获取路由表
                  localStorage.setItem('ROUTE_TABLE',"[]")
                  let url = `${process.env.VUE_APP_URL}/api/permission/menu`
                  axios.get(url).then(res=>{
                    if(res.data.success){
                      routeTable = res.data.data
                    }
                    localStorage.setItem('ROUTE_TABLE',JSON.stringify(res.data.data))
                    addRoutes(routeTable)
                    next()
                  })
                }
            } else {
                next('/user/login')
            }
        }).
        catch(error=>{
          next('/user/login')
        })}
// 在登录之后,进入首页之前进行路由表初始化
function initRouters(routeTable) {
 //遍历后台传来的路由字符串,转换为组件对象
  let newRoutes = []
  routeTable.forEach(route => {
    let oRouter = {}
    if (route.component) {
      oRouter  = {
        path: route.path,
        component(resolve) {
          .....//将后台返回的字符串转化为对应的组件对象
        },
        ....//路由相关信息
        hidden: route.hidden ? route.hidden : false,
        children: route.children && route.children.length > 0 ? initRouters(route.children) : []
       }
      if( oRouter.children.length == 0){
        delete oRouter.children
      }
    }
    newRoutes.push(oRouter)
  })
  return newRoutes
}
//增加新路由到路由表
function addRoutes(routeTable){
  let newRoutes = []
  let oldRoutes = routers
  routers.forEach(item=>{
    let obj = {}
    ......//生成新的路由表
    if(item.path == '/'){
      obj.children = item.children.concat(initRouters(routeTable))
    }
    newRoutes.push(obj)
  })
  Store.commit('SET_ROUTERS',newRoutes)
  router.addRoutes(newRoutes)

2.问题分析    

问题是页面刷新导致的,那我们就来分析下vue中页面刷新对于路由来说所走的流程。

vue加载main.js=>main.js调用router=>获取浏览器URL=>router根据路由表找对应的组件=>找到对应的组件,加载组件(在加载组件前router.beforEach())=>显示页面

理清楚上面的路由加载流程则不难看出问题出在router根据路由表找对应的组件(此时后台返回的路由数据还未加载到路由表中)

3.解决思路

既然加载顺序问题,那我们就需要一个能将后台返回的路由数据存储的功能(自然而然想到  localstorage)。

1)配置公共路由

2)首次登录成功将后台返回的路由数据存在localstorage中并且动态(addRoutes)将数据添加到路由表数组中

3)在公共路由router.js中判断本地localstorage的ROUTER_TABLE是否存在,如果不存在则正常加载,如果存在则取出localstorage中的ROUTER_TABLE并处理放入router.js的数组中

4)全局导航监听(router.beforEach(function(to,from,next){}),判断localstorage中的路由数据是否存在,如果存在处理后放入动态路由中(addRoutes),否则请求后台数据获取相关数据

4.相关代码

1)定义router.js配置公共路由
  let routers=[
     ..........
   ]
  export default routers
2)vue router全局导航钩子监听路由加载在进入动态路由对应的页面前使用addRoutes添加路由
  router.berforEach(function(to,from,next){
     .....请求后台,待数据返回
     axios.get(url).then(res=>{
      if(res.data.success){
        localstorage.setItem("ROUTER_TABLE")
        router.addRoutes(....)
      }
      }
  })
3)处理路由表router.js
let routeTable =localStorage.getItem("ROUTE_TABLE") ? JSON.parse(localStorage.getItem("ROUTE_TABLE")) : []
if(routeTable && routeTable.length > 0){ 
    routers =  addRoutes(routers)
}
function initRouters(routeTable) { 
//遍历后台传来的路由字符串,转换为组件对象  
let newRoutes = []  
routeTable.forEach(route => {
    let oRouter = {}
    if (route.component) {
    oRouter  = {
      path: route.path,
      component(resolve) {
       ....
    }
    newRoutes.push(oRouter)
  })
  return newRoutes
  }
 //增加新路由到路由表
function addRoutes(routers){
  let newRoutes = []
  routers.forEach(item=>{
    let obj = {}
    for(let key in item){
    obj[key] = item[key]
    }
    if(item.path == '/'){
    obj.children = item.children.concat(initRouters(routeTable))
    }    newRoutes.push(obj)  })
  Store.commit('SET_ROUTERS',newRoutes)
  return newRoutes
  }
4)最请参照第一段相关代码


相关文章
|
1天前
|
JavaScript
vue解决方案 | router-view路由切换时页面不刷新
vue解决方案 | router-view路由切换时页面不刷新
6 0
|
1天前
|
JavaScript
vue 自动注册路由
vue 自动注册路由
10 1
|
1天前
|
JavaScript
学习和分享关于 Vue.js 的路由(vue-router)
学习和分享关于 Vue.js 的路由(vue-router)
9 2
|
4天前
|
JavaScript 前端开发 程序员
探索Vue.js宝库:解锁基础知识与实用技能之门(1. 数据绑定与响应式 2. 条件与循环 3. 组件化开发;1. 路由管理与导航 2. 状态管理与Vuex 3. Vue.js的生命周期)
探索Vue.js宝库:解锁基础知识与实用技能之门(1. 数据绑定与响应式 2. 条件与循环 3. 组件化开发;1. 路由管理与导航 2. 状态管理与Vuex 3. Vue.js的生命周期)
12 1
|
4天前
|
JavaScript 前端开发
Vue.js中使用JavaScript实现路由跳转详解
Vue.js中使用JavaScript实现路由跳转详解
6 0
|
4天前
|
JavaScript
Vue搭配ELEMENT组件,路由不能正确跳转bug
Vue搭配ELEMENT组件,路由不能正确跳转bug
Vue搭配ELEMENT组件,路由不能正确跳转bug
|
5天前
|
JavaScript 前端开发 网络架构
Vue如何实现页面跳转路由,实现单页面跳转
Vue如何实现页面跳转路由,实现单页面跳转
|
5天前
|
JavaScript 网络架构
vue3 Elementplus 动态路由菜单不跳转问题
vue3 Elementplus 动态路由菜单不跳转问题
20 1
|
7天前
|
JavaScript API 网络架构
Vue3路由机制router(2)
Vue3路由机制router(2)
12 0
|
7天前
|
安全 定位技术 数据安全/隐私保护
Vue3路由机制router(1)
Vue3路由机制router(1)
17 0