记录解决动态路由页面刷新白屏问题

一、 问题代码       

        最近在实现前端动态路由时遇到一个问题,当我登录跳转到home页面时,页面空白。我的动态路由实现思路是封装一个initMenu函数,该函数通过请求后端菜单数据,对数据进行处理,将数据路由加入到router中,并将数据保存在vuex中方便后续使用。

initMenu代码:

import {getRequest} from "./api";



export const initMenu =  (router, store) => {

    return new Promise((resolve, reject) => {
        getRequest("/menu").then(res => {
            if (res && res.code === 200) {
                let fmtRoutes = formatRoutes(res.data);
                router.addRoutes(fmtRoutes);
                store.commit('initRoutes', fmtRoutes);
                resolve();
            } else {
                reject("菜单数据获取失败");
            }
        }).catch(err => {
            reject(err);
        });
    });

}


export const formatRoutes = (routes) => {
    let fmRoutes = [];
    routes.forEach(router => {
        let {
            path,
            component,
            name,
            meta,
            iconCls,
            children,
        } = router;
        if (children && children instanceof Array) {
            //递归
            children = formatRoutes(children);
        }
        let fmRouter = {
            path: path,
            name: name,
            meta: meta,
            iconCls: iconCls,
            children: children,
            component(resolve) {
                if (component.startsWith("Home")){
                    require(['../views/' + component + 'Vue.vue'], resolve);
                }else if (component.startsWith("Emp")) {
                    require(['../views/emp/' + component + '.vue'], resolve);
                } else if (component.startsWith("Per")) {
                    require(['../views/per/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sal")) {
                    require(['../views/sal/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sta")) {
                    require(['../views/sta/' + component + '.vue'], resolve);
                } else if (component.startsWith("Sys")) {
                    require(['../views/sys/' + component + '.vue'], resolve);
                }
            }
        }
        fmRoutes.push(fmRouter);
    })
    return fmRoutes;
}

路由守卫代码:

router.beforeEach( async (to, from, next) => {
    if (to.path === '/login') {
        next()
    }

    if (sessionStorage.getItem("token")) {
        //用户已登录获取用户信息
        const res = await getRequest("/admin/info")
            if (res) {
                sessionStorage.setItem('user', JSON.stringify(res.data))
            }
        if (store.state.routes.length > 0) {
            next()
        } else {
            //获取菜单数据
            await initMenu(router, store)
            next()
        }

    } else {
        //若用户未登录跳回登录页面
        next("/login")
    }

})

  二、问题描述

        进入子路由页面后,刷新会出现空白,我在网上查了许多解决方法,基本意思是说路由在还未加载完成就进行了路由跳转,但是我在路由守卫获取菜单数据的方法前加了await,理论上来说,在进入到新路由前,我的菜单数据应该是准备好的。

三、问题原因与解决方法

        首先问题原因确实是路由还未加载完成就进行了路由跳转,至于为什么使用了await没有解决问题,原因是即使使用await等待菜单数据加载上了,但是Vue Router使用的是旧的路由表,旧的路由表是没有动态路由的数据的,相当于路由跳转到一个不存在的路由上,从而页面白屏。

        解决方法是在获取动态路由后使用next({...to,replace:true})进行放行,该代码的意思是触发一次新的导航到当前正在访问的地址,进行新的导航时,路由数据已经准备就绪,页面就可以正常的展示了。

 Vue Router导航流:

        导航开始时->根据当时的路由表做一次匹配->匹配到组件后,进入渲染流程

 导航中途即使修改了路由表,当前导航不会自动重新匹配,必须重新发起一次导航,让Vue Router走一遍完整的匹配。

具体例子:

        页面刷新相当于Vue Router开车通过地图从A地前往A地,开车到一半发现没有地图上没有A地,于是迷路(页面空白),此时即使更新完地图(补充动态路由),但是车已经在迷路状态,Vue Router不会自己掉头用新地图再去一次A地,此时需要使用next({...to, replace:true}让Vue Router再次出发前往A地,第二次Vue Router就使用最新的地图(更新完后的路由表)。

修改后的路由守卫代码:

router.beforeEach( async (to, from, next) => {
    const token = sessionStorage.getItem("token");

    if (to.path === '/login') {
        next();
    } else if (token) {
        if (!sessionStorage.getItem('user')) {
                const res = await getRequest('/admin/info');
                if (res) {
                    sessionStorage.setItem('user', JSON.stringify(res.data));
                }
        }

        if (store.state.routes.length === 0) {
                await initMenu(router, store);
                next({ ...to, replace: true });
        } else {
            next();
        }
    } else {
        next('/login');
    }
});

        

页面白屏问题是因为刷新页面时,vuex中的数据会丢失,导致动态添加的路由失效[1]。为了解决这个问题,可以将路由信息存储在sessionStorage中,但需要注意的是,只存储了左侧菜单栏展示的信息path地址,并没有存储路由详细信息,比如name和meta值。因此,我们可以使用路由守卫,在每次页面刷新时判断是否添加了动态路由。如果没有添加,则再次执行添加动态路由的过程即可。 在store.js的mutations中添加动态路由的代码,可以通过设置一个变量来记录是否已经添加了动态路由的布尔值。在路由守卫中,判断这个变量的值,如果为false,则执行添加动态路由的过程,然后调用next()继续页面的跳转。 使用路由懒加载也是解决页面白屏问题的常用方法。路由懒加载即延迟加载或按需加载,可以提升首屏组件加载速度,解决白屏问题。在vue2中,可以使用动态import语法来实现路由懒加载。将组件的import语句放在路由配置中的component字段中,并使用箭头函数来动态导入组件。 下面是解决页面白屏问题的步骤: 1.路由信息存储在sessionStorage中,包括左侧菜单栏展示的信息path地址。 2. 在store.js的mutations中添加动态路由的代码,并设置一个变量记录是否已经添加了动态路由的布尔值。 3. 使用路由守卫,在每次页面刷新时判断是否添加了动态路由。如果没有添加,则再次执行添加动态路由的过程,并调用next()继续页面的跳转。 4. 使用路由懒加载来提升首屏组件加载速度,解决白屏问题。在vue2中,可以使用动态import语法来实现路由懒加载,将组件的import语句放在路由配置中的component字段中,并使用箭头函数来动态导入组件。 通过以上步骤,可以解决vue2路由配置完页面白屏问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值