100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 一行代码解决Vue异步路由刷新后404的问题

一行代码解决Vue异步路由刷新后404的问题

时间:2023-08-09 16:12:34

相关推荐

一行代码解决Vue异步路由刷新后404的问题

背景

/home:项目首页,同步路由

/uc/profile:个人信息页,异步路由,登录后根据用户角色展示。

/login?redirect=%2Fuc%2Fprofile(%2F是/ 的url转义) :登录页,同步路由,在个人信息页退出登录会进入登录页并携带redirect=/uc/profile,再次登录成功后,直接进入个人信息页

项目:基于vue-element-admin,对权限菜单,异步路由,Mock文件都已经写好了。只需要根据需求修改就可以!

问题:

最开始项目没有配置重定向404(路由没有{path:"*",redirect:"/"}),在/uc/profile页面刷新可以重新显示,并且退出登录后重新登录也可以再次显示页面。

此时路由配置:

// 同步路由export const constantRoutes = [...homeRouter,{path: "/404",component: () => import("@/views/error-page/404"),hidden: true}];// 异步路由(通过后端获取或者前端筛选添加)export const asyncRoutes = [{path: "/uc",component: Layout,children: [{path: "profile",component: () => import("@/views/manage/profile"),name: "Profile",meta: { title: "个人信息", icon: "el-icon-user" }},{ path: "*", redirect: "/404", hidden: true }]}];// beforeEachrouter.beforeEach(async (to, from, next) => {const hasToken = getToken();if (hasToken) {if (to.path === "/login") {next();} else {const hasRoles = store.getters.roles && store.getters.roles.length > 0;if (hasRoles) {next();} else {try {const { roles } = await store.dispatch("user/getInfo");const accessRoutes = await store.dispatch("permission/generateRoutes",roles);router.addRoutes(accessRoutes);next({ ...to, replace: true });} catch (error) {await store.dispatch("user/resetToken");next(`/login?redirect=${to.path}`);}}}} else {if (whiteList.indexOf(to.path) !== -1) {next();} else {next(`/login?redirect=${to.path}`);}}});

效果:

存在的问题:输入错误的路径,例如:/home1,只会显示白屏。

为了处理错误的路径,给路由添加重定向;这是输入/home1可以重定向到404页了;

export const constantRoutes = [...homeRouter,{path: "/404",component: () => import("@/views/error-page/404"),hidden: true},{ path: "*", redirect: "/404" } // 添加];

效果:

存在的问题:错误路径可以重定向到404了,但是异步路由页面刷新会重定向到404,并且在异步路由页面退出登录,再登录后自动重定向到异步路由的页面也会404;

这时的from和to如下,from变成了null,to是404

其他解决方案:

网上看了不少博客,基本都是使用sessionStorage去在监听unload事件,在刷新的时候去报存异步页面的路径;在beforeEach中addRoute之后,判断sessionStorage,去跳转到异步页面;

// App.vuewatch: {$route: () => {window.addEventListener("beforeunload", () => { // unload也一样sessionStorage.setItem("tp", window.location.pathname);});},},-----------------------// beforeEach.....router.addRoutes(accessRoutes);let p = sessionStorage.getItem("tp");if (p.startsWith('/uc')) { // 判断是否为异步路由sessionStorage.removeItem("tp");router.replace(p);} else {sessionStorage.removeItem("tp");next({ ...to });}....

这样解决异步路由的问题,但是又产生了其他问题。

你需要在获取到sessionStorage之后去判断这个路径是不是异步的(如果不判断的话,你在页面通过a的href是无法跳转的,并且你在/home页下故意输入错误路径/home1,并不会重定向到404,会重新回到/home页面等许多问题)。

最终方案

beforeEach的to参数,有一个redirectedFrom属性,可以根据这个属性来进行判定。

// beforeEach...router.addRoutes(accessRoutes);if (to.redirectedFrom) {router.replace(to.redirectedFrom);} else {next({ ...to });}...

这个方式,不需要监听unload事件,不需要判定路径是否为异步

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。