背景

/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 }
    ]
  }
];
// beforeEach
router.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.vue
watch: {
    $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事件,不需要判定路径是否为异步

Logo

前往低代码交流专区

更多推荐