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

Vue3登录状态存储求助:路由切换后状态丢失

问题解决:Vue3登录后导航栏状态路由切换丢失

你的核心问题是登录状态仅存于Login组件的局部data中,路由切换时Login组件销毁,状态随之丢失;同时你虽使用了Vuex,但未将登录状态维护在全局store里,反而用组件传参的方式,导致状态无法跨路由持久化。以下是具体修正方案:


步骤1:用Vuex全局维护登录状态

先完善Vuex的auth模块,专门处理登录状态:

// store/modules/auth.js
export default {
  namespaced: true,
  state: {
    isLoggedIn: false
  },
  mutations: {
    SET_LOGIN_STATUS(state, status) {
      state.isLoggedIn = status;
    }
  },
  actions: {
    // 登录接口调用
    async login({ commit }, credentials) {
      const response = await this.$axios.post('/api/login', credentials);
      const data = response.data;
      if (data.success) {
        commit('SET_LOGIN_STATUS', true);
        // 存token到localStorage,实现刷新页面保持登录
        localStorage.setItem('token', data.token);
      }
      return data;
    },
    // 登出
    logout({ commit }) {
      commit('SET_LOGIN_STATUS', false);
      localStorage.removeItem('token');
    },
    // 页面刷新时恢复登录状态
    checkLogin({ commit }) {
      const token = localStorage.getItem('token');
      if (token) {
        // 可额外验证token有效性,这里做简单处理
        commit('SET_LOGIN_STATUS', true);
      }
    }
  },
  getters: {
    isLoggedIn: state => state.isLoggedIn
  }
};

在store主文件注册模块:

// store/index.js
import { createStore } from 'vuex';
import auth from './modules/auth';

export default createStore({
  modules: {
    auth
  }
});

步骤2:修正Navbar组件,直接读取全局状态

删除冗余的props和局部data,直接从Vuex获取状态:

<template> 
  <nav class="navbar-light bg-light">
    <ul class="ul1">
      <li><router-link to="/"> <button class="btn inscription-button"> Accueil </button> </router-link></li>
      <li><router-link to="/informations" class="btn inscription-button"> Informations </router-link></li>
      <li><router-link to="/tasklist" class="btn inscription-button"> Liste de tâches </router-link></li>
      <!-- 直接用Vuex全局状态控制显示 -->
      <router-link to="/createtask" v-if="isLoggedIn" class="btn inscription-button"> Créer une tâche </router-link>  
      <li><router-link to="/contact" class="btn inscription-button"> Contact </router-link></li>
    </ul>
    <ul>
      <li v-if="!isLoggedIn">
        <router-link to="/login">Login</router-link>
      </li>
      <li v-if="isLoggedIn">
        <button @click="logout">Logout</button>
      </li>
    </ul>
  </nav>
</template>

<script>
import { mapActions, mapGetters } from 'vuex';

export default {
  name: 'Navbar',
  computed: {
    // 从Vuex获取全局登录状态
    ...mapGetters('auth', ['isLoggedIn'])
  },
  methods: {
    // 调用Vuex的登出action
    ...mapActions('auth', ['logout']),
  },
  // 页面加载时检查登录状态,刷新页面也能保留
  mounted() {
    this.$store.dispatch('auth/checkLogin');
  }
};
</script>

步骤3:修正Login组件,移除局部状态和重复Navbar

Login组件无需单独引入Navbar(App.vue已全局挂载),登录成功后更新Vuex状态:

<template>
  <!-- 移除重复的Navbar组件 -->
  <section class="vh-100">
    <div class="container py-5 h-100">
      <div class="row d-flex align-items-center justify-content-center h-100">
        <div class="col-md-8 col-lg-7 col-xl-6">
          <img src="https://mdbcdn.b-cdn.net/img/Photos/new-templates/bootstrap-login-form/draw2.svg"
            class="img-fluid" alt="Phone image">
        </div>
        <div class="col-md-7 col-lg-5 col-xl-5 offset-xl-1">
          <form @submit.prevent="submitForm">
            <div class="form-outline mb-4">
              <input type="email" id="form1Example13" class="form-control form-control-lg" required v-model="email" name="user_mail" />
              <label class="form-label" for="form1Example13">Adresse email</label>
            </div>
            <div class="form-outline mb-4">
              <input type="password" id="form1Example23" class="form-control form-control-lg" required v-model="password" name="user_password" />
              <label class="form-label" for="form1Example23">Mot de passe</label>
            </div>
            <div class="d-flex justify-content-around align-items-center mb-4">
              <div class="form-check">
                <input class="form-check-input" type="checkbox" value="" id="form1Example3" checked />
                <label class="form-check-label" for="form1Example3"> Se souvenir de moi </label>
              </div>
              <a href="#!">Mot de passe oublié ?</a>
            </div>
            <button type="submit" class="btn btn-primary btn-lg btn-block">Se connecter</button>
            <div class="divider d-flex align-items-center my-4"></div>
          </form>
        </div>
      </div>
    </div>
  </section>
</template>

<script>
import { mapActions } from "vuex";
import Swal from 'sweetalert2'

export default {
  data() {
    return {
      email: '',
      password: ''
      // 移除局部的isLoggedIn状态
    }
  },
  methods: {
    submitForm: async function () { 
      const response = await this.login({
        email: this.email,
        password: this.password
      });

      if(response.success) {
        Swal.fire({
          title: 'Connexion réussie ! ',
          text: response.message,
          icon: 'success'
        });
        this.$router.push('/tasklist')
      } else {
        Swal.fire({
          title: 'Connexion échouée ',
          text: response.message,
          icon: 'error'
        });
      }
    },
    // 调用Vuex的登录action
    ...mapActions("auth", ["login"]),
  }
}
</script>

步骤4:App.vue全局挂载Navbar

确保整个应用只有一个Navbar实例,所有路由页面共用:

<template>
  <Navbar />
  <router-view />
</template>

<script>
import Navbar from './components/Navbar.vue';

export default {
  components: {
    Navbar
  }
}
</script>

为什么之前的方法失效?

  1. 局部状态丢失:登录状态存在Login组件的data中,路由切换后组件销毁,状态随之消失;
  2. 多Navbar实例:每个页面单独引入Navbar会创建多个独立实例,状态无法共享;
  3. 状态维护混乱:同时使用props、局部data和Vuex,导致状态同步逻辑冲突。

现在通过Vuex全局维护状态,配合全局Navbar实例,就能保证路由切换时状态持久化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 00:31:03