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

Vue.js 3如何防止已认证页面刷新时闪现登录页面

问题:Vue3刷新已认证页面时登录页面闪现的解决方法

原因分析

问题核心在于页面初始渲染时,Vuex的isLogin默认是未认证的false,而登录状态校验逻辑fetchUserLogin是在onMounted钩子中才执行。这就导致页面先渲染了login组件,等异步的登录校验完成后才切换到router-view,从而出现登录页面闪现的情况。另外当前路由守卫未做任何权限校验,直接放行所有路由,也会加剧这种问题。

解决方案

1. 改造App.vue:等待登录校验完成后再渲染内容

添加加载状态,避免初始阶段直接渲染登录组件,等登录状态确认后再展示对应内容。

修改后的App.vue:

<template>
  <!-- 校验未完成时显示加载态,阻断错误渲染 -->
  <div v-if="isCheckingLogin" class="loading">加载中...</div>
  <router-view v-else-if="store.state.isLogin"/>
  <login v-else></login>
</template>

<script setup lang="ts">
import Login from '@/components/Login.vue'
import { useStore } from 'vuex';
import { ref, onBeforeMount } from "vue";

const store = useStore();
const isCheckingLogin = ref(true);

// 提前到onBeforeMount执行,更早触发登录校验
onBeforeMount(async ()=>{
  await store.dispatch('fetchUserLogin');
  // 校验完成后关闭加载状态
  isCheckingLogin.value = false;
});
</script>

<style scoped>
.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  font-size: 18px;
}
</style>

2. 完善路由守卫:跳转前先校验登录状态

利用router.beforeEach在路由跳转前完成登录校验,同时处理不同路由的权限逻辑,避免未校验就进入页面。

修改后的router/index.ts:

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import Login from '@/components/Login.vue'
// @ts-ignore
import { store } from "@/vuex/store";

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes: [
        {
            path: '/login',
            name: 'login',
            component: Login,
            // 已登录用户访问登录页直接跳首页
            meta: { requiresGuest: true }
        },
        {
            path: '/home',
            name: 'home',
            component: HomeView,
            // 需要登录才能访问
            meta: { requiresAuth: true }
        },
        // 404路由重定向
        {
            path: '/:pathMatch(.*)*',
            redirect: '/home'
        }
    ]
})

router.beforeEach(async (to, from, next) => {
  // 首次进入/刷新时,先确认登录状态
  if (store.state.isLogin === undefined || store.state.isLogin === null) {
    await store.dispatch('fetchUserLogin');
  }

  // 拦截未登录用户访问需认证路由
  if (to.meta.requiresAuth && !store.state.isLogin) {
    next({ name: 'login' });
  } 
  // 拦截已登录用户访问登录页
  else if (to.meta.requiresGuest && store.state.isLogin) {
    next({ name: 'home' });
  } 
  // 其他情况正常放行
  else {
    next();
  }
})

export default router

3. 优化Vuex状态初始化

从本地存储预判断登录状态,减少校验等待时间,避免初始状态完全为false:

修改后的store.js示例:

// @/vuex/store.js
import { createStore } from 'vuex'

export const store = createStore({
  state: {
    // 初始时从本地存储读取token,初步判断登录状态
    isLogin: !!localStorage.getItem('token'),
    token: localStorage.getItem('token') || '',
    user: null
  },
  mutations: {
    SET_TOKEN(state, token) {
      state.token = token;
      localStorage.setItem('token', token);
      state.isLogin = true;
    },
    SET_USER(state, user) {
      state.user = user;
    },
    LOGOUT(state) {
      state.token = '';
      state.user = null;
      state.isLogin = false;
      localStorage.removeItem('token');
    }
  },
  actions: {
    async fetchToken({ commit }, credentials) {
      // 替换为你的登录接口请求逻辑
      const res = await fetch('/api/login', {
        method: 'POST',
        body: JSON.stringify(credentials)
      });
      const data = await res.json();
      commit('SET_TOKEN', data.token);
    },
    async fetchUserLogin({ state, commit }) {
      if (!state.token) {
        commit('LOGOUT');
        return;
      }
      // 替换为你的token校验/用户信息获取接口
      try {
        const res = await fetch('/api/user', {
          headers: {
            Authorization: `Bearer ${state.token}`
          }
        });
        if (res.ok) {
          const user = await res.json();
          commit('SET_USER', user);
        } else {
          commit('LOGOUT');
        }
      } catch (err) {
        commit('LOGOUT');
      }
    }
  }
})

关键要点总结

  • 提前执行登录校验:把校验逻辑从onMounted移到onBeforeMount或路由守卫中,避免页面先渲染错误内容
  • 添加加载过渡:用加载态阻断未校验时的组件渲染,消除闪现
  • 路由权限全覆盖:处理已登录/未登录用户的路由跳转逻辑,避免非法访问
  • 状态预初始化:从本地存储预判断登录状态,缩短校验等待窗口

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 12:55:25