LOADING

[Vue Router]解决动态路由刷新白屏问题

解决动态路由刷新白屏问题

这个算是遗留比较久的问题了,以前做项目的时候也遇到过,今天总算找到了解决方法

问题描述

由于需要做后台的权限控制,权限菜单需要后端发送数据,前端按需生成对应选项卡,这样就需要用到动态路由了,以下是一个动态路由的例子

// //前置导航守卫
router.beforeEach((to, from, next) => {
    // 判断token,menu是否为空
    console.log(from.path + "=>" + to.path);

    if (getToken() && getItem("adminInfo") && to.path == "/login") {
        alert("您已登录!");
        router.push("/homepage");
    }
    if ((!getToken() || !getItem("adminInfo")) && to.path != "/login") {
        alert("未登录");
        router.push("/login");
    }

    //当store.$state.menus.length没有初始化好的时候才需要执行
    if (getToken() && getItem("adminInfo")) {
        //循坏菜单对象(动态路由)
        const menus = store.getMenus as NewMenu;
        //遍历添加路由,遍历创建路由
        for (let key in menus) {
            //获取一级路由
            const newRoutes: RouteRecordRaw = {
                path: "/" + menus[key].name,
                name: menus[key].name,
                component: () => import("@/views/HomePage/HomePage.vue"),
                children: [],
            };
            //遍历创建二级路由
            for (let i = 0; i < menus[key].children.length; i++) {
                newRoutes.children?.push({
                    path: menus[key].children[i].name,
                    name: menus[key].children[i].name,
                    component: () =>
                    import(
                        `@/views/${menus[key].name}/${menus[key].children[i].name}.vue`
                    ),
                });
            }
            //添加路由到全局
            router.addRoute(newRoutes);
        }
        console.log(router.getRoutes());
        console.log(menus, "router-menus");
    } else {
        next();
    }
});

以上是一个简单的路由守卫钩子,他负责路由鉴权以及动态生成路由,使用了localStorage存储菜单数据,pinia存储处理后的菜单数据,看上去没有问题,实则第一次点击确实可以进入路由,但是刷新后就会白屏
控制台显示:[Vue Router warn]: No match found for location with path "/pms/product"

解决方法

只需要在动态生成路由的功能入口判断一下store的menu是否已经就绪,然后在里面重定向一下当前路由next(to.path);
由于第二次进入路由守卫时menus已经准备就绪,所以就直接执行next()指令

//当store.$state.menus.length没有初始化好的时候才需要执行
if (getToken() && getItem("adminInfo") && store.$state.menus.length == 0) {
    /*.......*/
    //防止白屏,因为next的时候其实动态路由并没有初始化好,所以还需要to.path执行一次路由守卫
    next(to.path);
} else {
    next();
}

这样就解决了刷新白屏的问题,但是控制台的警告依旧存在...
这是因为第一次进入路由的时候,动态路由是在默认路由之后才执行的,所以警告会首先触发,我们可以通过添加一个通配符路由捕获掉第一次 ”不存在“ 的路由信息:

const routes: Array<RouteRecordRaw> = [
    /*......*/
    //添加一个全局路由用于捕获不存在的页面
    {
    path:'/:404(.*)',//404是我自己定义的名字,当然你也可以定义其他值
    component:()=>import('@/views/404.vue')
}]

    发表回复

    电子邮件地址不会被公开。必填项已用 * 标注