vue-router导航守卫动态菜单显示空白,刷新才恢复

原先的代码:

--- main.js ---

import router from './router'
import store from './store'

router.beforeEach((to, from, next) => {
  //如果存在token
  if (window.sessionStorage.getItem("tokenStr")) {
    //是不是要去登录页,登录了就不给去了
    if (to.path == '/') {
      next('/home')
    } else {
      //如果登录了并且不是去登录页,就获取一遍菜单
		initMenu(router,store)
      if (!window.sessionStorage.getItem('user')) {
        //如果没有用户信息就获取
        return getRequest('/system/config/info').then(resp => {
          if (resp && resp.success != false) {
            //存入用户信息
            window.sessionStorage.setItem('user', JSON.stringify(resp))
            next()
          }
        })
      } else {
        next();
      }
    }
  } else {
    //不存在token要去登录页就放行,不去登录页就强制进入登录页并带上重定向参数
    if (to.path == '/') {
      next();
    } else {
      next('/?redirect=' + to.path);
    }
  }
})
--- menu.js ---

if (store.state.routes.length > 0) {
	next()
}
getRequest('/system/config/menu').then(data => {
  // console.log(data)
  if (data) {
    let fmtRoutes = formatRoutes(data);
    //添加到路由
    console.log("添加菜单")
    router.addRoutes(fmtRoutes)
    store.commit("initRoutes", fmtRoutes);
  }
})

export const formatRoutes = (routes) => {
    let fmtRoutes = [];
    routes.forEach(router => {
        let {
            path,
            component,
            name,
            iconCls,
            children,
        } = router;
        if (children && children instanceof Array) {
            //递归
            children = formatRoutes(children);
        }
        let fmtRouter = {
            path: path,
            name: name,
            iconCls: iconCls,
            children: children,
            component(resolve) {
                if (component.startsWith("Home")) {
                    require(['../views/' + component + '.vue'], resolve);
                } else if (component.startsWith("Manage")) {
                    require(['../views/mng/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sys")) {
                    require(['../views/sys/' + component + '.vue'], resolve);
                } else if (component.startsWith("Obj")) {
                    require(['../views/obj/' + component + '.vue'], resolve);
                }
            }
        }
        fmtRoutes.push(fmtRouter)
    })
    return fmtRoutes;
}

很显然我原先的方法是在路由导航守卫中进行条件判断然后调用获取动态菜单的方法,然而,经过调试,这种通过调用的方式,还没等菜单获取完,路由守卫就继续执行下去了,也就是异步执行,类似于ajax里面的嵌套,于是我们便得到了空白页。
所以,我们需要让动态菜单先加载完毕,我这边用的方法是把获取菜单的方法搬过来

修改后的代码:

--- main.js ---

router.beforeEach((to, from, next) => {
 //如果存在token
 if (window.sessionStorage.getItem("tokenStr")) {
   //是不是要去登录页,登录了就不给去了
   if (to.path == '/') {
     next('/home')
   } else {
     //如果登录了并且不是去登录页,就获取一遍菜单
     if (store.state.routes.length > 0) {
       if (!window.sessionStorage.getItem('user')) {
         //如果没有用户信息就获取
         console.log("无用户信息")
         return getRequest('/system/config/info').then(resp => {
           if (resp && resp.success != false) {
             //存入用户信息
             window.sessionStorage.setItem('user', JSON.stringify(resp))
             next()
             return;
           }
         })
       } else {
         next();
         return;
       }
     }
     getRequest('/system/config/menu').then(data => {
       // console.log(data)
       if (data) {
         //进行菜单的格式化操作
         let fmtRoutes = formatRoutes(data);
         //添加到路由
         console.log("添加菜单")
         router.addRoutes(fmtRoutes)
         store.commit("initRoutes", fmtRoutes);
         next({...to,replace:true})
       }
     })


   }
 } else {
   //不存在token要去登录页就放行,不去登录页就强制进入登录页并带上重定向参数
   if (to.path == '/') {
     next();
   } else {
     next('/?redirect=' + to.path);
   }
 }
})

但即使你搬过来,还是阻止不了异步执行,于是,在搬过来之后还多写了这么一个东西
next({...to,replace:true})(关于这句话的详细释义,我把参考文章放在下面链接了)
我的理解如下:意思是先暂时中断当前的路由守卫,带着…to的参数再去访问路由守卫,形成了一个嵌套,那第二遍执行的时候仍然会执行这句话,这不就无限嵌套了吗,所以为了防止无限嵌套,必须要有一个终止条件,那我的终止条件就是当我的菜单添加成功并添加到vuex中之后,然后再一层一层结束最后回到最外层,再顺序执行,这样就可以保证菜单先加载完了。

--- 终止条件 ---
if (store.state.routes.length > 0) {
  next()
  return
}

本文参考:https://blog.csdn.net/qq_41912398/article/details/109231418

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值