You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue-Router中间件配置问题:刷新子路由跳转至父路由

问题分析

刷新dashboard子路由后自动跳转到home的核心原因是页面刷新时Pinia Store初始化存在时序问题,路由钩子中token的初始值不准确,导致触发两次重定向:

  1. 刷新后Pinia Store初始化未完成,token初始值为null/undefined,router.beforeEach检测到未登录,跳转到login
  2. login的前置钩子执行时,Store已完成初始化,token值已加载,因此又跳转到home
解决方案
  1. 移除路由文件中提前定义的computed token,直接从Store获取最新值,避免时序问题
  2. 确保Auth Store同步从本地存储初始化token,保证路由钩子触发时token值准确
  3. 优化router.beforeEach逻辑,等待用户信息加载完成后再执行权限判断
  4. 修正各路由前置钩子的取值方式,直接使用Store状态
修改后的代码
// Main Router
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'index',
      component: LandingView,
    },
    {
      path: '/login',
      name: 'login',
      component: LoginView,
      beforeEnter: (to, from, next) => {
        const authStore = useAuthStore();
        if (authStore.token) {
          return next({ name: 'home' });
        }
        next();
      },
    },
    {
      path: '/signup/:uid?',
      name: 'signup',
      component: SignupView,
    },
    {
      path: '/dashboard',
      name: 'dashboard',
      component: DashboardLayout,
      children: [
        {
          path: '',
          name: 'home',
          component: HomeView,
        },
        {
          path: 'profile',
          name: 'profile',
          component: ProfileView,
        },
        {
          path: 'deposit',
          name: 'deposit',
          component: DepositView,
        },
        {
          path: 'pay-amount/:amount?',
          name: 'pay-amount',
          component: PayAmountView
        },
        {
          path: 'referral',
          name: 'referral',
          component: ReferralView,
        },
        {
          path: 'salary',
          name: 'salary',
          component: SalaryView,
        },
      ],
      meta: {
        requiresAuth: true,
        requiresEmailVerify: true,
        requiresPayment: true,
        requireKyc: true,
      },
    },
    {
      path: '/email-verify',
      name: 'email-verify',
      component: EmailVerifyView,
      meta: { requiresEmailVerify: false },
      beforeEnter: (to, from, next) => {
        const authStore = useAuthStore();
        if (!authStore.email) {
          next({ name: 'login' });
        }
        next();
      },
    },
  ],
});

router.beforeEach(async (to, from, next) => {
  const authStore = useAuthStore();
  const userStore = useUserStore();
  const token = authStore.token;

  // 确保token存在且用户信息未加载时,等待获取完成
  if (token && !userStore.user?.id) {
    try {
      await userStore.getUserDetails();
    } catch (err) {
      // 处理请求失败,清除token并跳转登录
      authStore.clearToken();
      return next({ name: 'login' });
    }
  }

  // 权限判断
  if (to.meta.requiresAuth && !token) {
    return next({ name: 'login' });
  } 
  
  if (to.meta.requiresEmailVerify && userStore.user?.email_verified === false) {
    return next({ name: 'email-verify' });
  }

  // 补充其他权限判断逻辑(示例)
  if (to.meta.requiresPayment && !userStore.user?.payment_done) {
    return next({ name: 'pay-amount' });
  }

  if (to.meta.requireKyc && !userStore.user?.kyc_verified) {
    // return next({ name: 'kyc' }); // 若有KYC页面可开启
  }

  next();
});

router.afterEach(() => {
  const {sidebarVisible, setSidebarVisible} = useLayoutStore();
  if (sidebarVisible) {
    setSidebarVisible(false);
  }
});

export default router;
额外注意事项
  • 确保Auth Store同步从本地存储初始化token,示例:
    export const useAuthStore = defineStore('auth', {
      state: () => ({
        token: localStorage.getItem('token') || null,
        email: localStorage.getItem('email') || null
      }),
      // ...其他方法
    })
    
  • 异步获取用户信息时需捕获异常,避免因请求失败导致权限判断混乱
  • 所有路由钩子中直接从Store取数,不要使用提前定义的响应式变量,保证数据实时性

内容的提问来源于stack exchange,提问作者Gursahb Webcyst

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:06:02