Vue 项目中登录组件重复加载及页面加载问题的排查与解决

目录

《Vue 项目中登录组件重复加载及页面加载问题的排查与解决》

一、问题描述

登录组件重复加载

页面一直加载转圈

二、问题排查与解决

登录组件重复加载问题

1. 路由配置文件(router/index.ts)

2. LoginPage.vue组件自身

3. LoginForm.vue组件引用

页面一直加载转圈问题

1. 路由守卫中的useStore问题

2. 路由重定向逻辑

三、总结


在 Vue 项目开发过程中,我们常常会遇到各种问题。本文将详细介绍在一个象棋游戏 Vue 项目中遇到的登录组件重复加载以及页面一直加载转圈的问题,包括问题的分析过程和相应的解决方法。

一、问题描述

登录组件重复加载

在项目中,发现登录页面(LoginPage.vue)及其包含的登录表单组件(LoginForm.vue)被重复加载。从控制台日志可以看到,LoginPage组件的createdmounted钩子函数以及LoginForm组件的createdmounted钩子函数都被执行了两次。

页面一直加载转圈

在对路由守卫相关代码进行修改后,页面出现一直加载转圈的情况,无法正常显示内容。

二、问题排查与解决

登录组件重复加载问题

1. 路由配置文件(router/index.ts

  • 问题分析
    • router/index.tsbeforeEach路由守卫中,对登录状态的判断和重定向逻辑可能存在问题。当用户未登录且访问某些需要登录的页面(如'/navigation''/game''/lobby')时,会重定向到登录页面('/')。但是,如果在某些特殊情况下,比如当前页面已经是登录页面,可能会因为没有正确处理这种情况而导致重复重定向,进而使登录组件重复加载。
  • 解决方法
    • 对路由守卫逻辑进行修改,添加更多的判断条件。以下是修改后的router/index.ts关键代码片段:

import { createRouter, createWebHistory } from 'vue-router';
import LoginPage from '../pages/LoginPage.vue';
import NavigationPage from '../pages/NavigationPage.vue';
import ChessGamePage from '../pages/ChessGamePage.vue';
import GameLobbyPage from '../pages/GameLobbyPage.vue';
import { useStore } from 'vuex';

const routes = [
    { path: '/', component: LoginPage },
    { path: '/navigation', component: NavigationPage },
    { path: '/game', component: ChessGamePage },
    { path: '/lobby', component: GameLobbyPage },
];

const router = createRouter({
    history: createWebHistory(),
    routes,
});

router.beforeEach((to, from, next) => {
    const store = useStore();
    console.log('路由守卫 - beforeEach', to.path, from.path);
    const isLoggedIn = store.state.auth.isLoggedIn;
    if (to.path === '/') {
        if (isLoggedIn) {
            // 如果已经登录,重定向到导航页面(可根据实际需求调整)
            next('/navigation');
        } else {
            next();
        }
    } else if (to.path === '/navigation' || to.path === '/game' || to.path === '/lobby') {
        if (!isLoggedIn) {
            // 如果未登录且访问需要登录的页面,重定向到登录页面
            if (from.path!== '/') {
                next('/');
            } else {
                // 如果当前页面已经是登录页面,不进行重定向
                next(false);
            }
        } else {
            next();
        }
    } else {
        next();
    }
});

router.afterEach((to, from) => {
    console.log('路由此题 - afterEach', to.path, from.path);
});

export default router;

2. LoginPage.vue组件自身

  • 问题分析
    • 组件内部可能存在一些条件渲染逻辑或者与其他组件的交互逻辑,导致其被多次加载。虽然从提供的代码中暂时没有发现明显问题,但需要进一步排查。
  • 解决方法
    • LoginPage.vuetemplate部分添加一个唯一的key属性,以便 Vue 能够更准确地识别组件的实例。修改后的LoginPage.vue部分代码如下:

<template>
  <div class="login-page" :key="'login-page-key'">
    <LoginForm />
  </div>
</template>
<script lang="ts">
import LoginForm from '../components/LoginForm.vue';
import { defineComponent } from 'vue';

export default defineComponent({
  components: {
    LoginForm,
  },
  created() {
    console.log('LoginPage - created');
  },
  mounted() {
    console狠簡 - mounted');
  },
});
</script>
<style scoped>
.login-page {
  background-image: url('../assets/images/login-background.jpg');
  background-size: cover;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>

3. LoginForm.vue组件引用

  • 问题分析
    • LoginPage.vue中对LoginForm组件的引用方式可能存在问题,或者组件自身的某些逻辑导致了多次创建和挂载。
  • 解决方法
    • 检查LoginPage.vue中对LoginForm组件的引用是否正确,确保只有一处引用。同时,在LoginForm.vuetemplate部分也添加一个唯一的key属性。修改后的LoginForm.vue部分代码如下:

<template>
  <div :key="'login-form-key'">
    <h2>Login Form</h2>
    <input type="text" v-model="username" placeholder="Username" />
    <input type="password" v-model="password" placeholder="Password" />
    <button @click="login">Login</button>
    <p v-if="errorMessage" class="error">{{ errorMessage }}</p>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  data() {
    return {
      username: '',
      password: '',
      errorMessage: '',
    };
  },
  created() {
    console.log('LoginForm组件 - created');
  },
  mounted() {
    console.log('LoginForm组件 - mounted');
  },
  methods: {
    login() {
      // 假设调用API进行登录,模拟登录失败的情况
      if (username === 'wrong' && password === 'wrong') {
        this.errorMessage = 'Invalid username or password';
      } else {
        // 成功登录的逻辑
      }
    },
  },
});
</script>
<style scoped>
.error {
 只、色: red;
}
</style>

页面一直加载转圈问题

1. 路由守卫中的useStore问题

  • 问题分析
    • 在路由守卫中使用了useStore来获取Vuexstore实例。如果useStore没有正确获取到store,可能会导致后续对store.state的访问出现问题,从而影响路由的正确跳转和页面加载。
  • 解决方法
    • 直接导入store实例,避免了useStore可能出现的获取不到store的问题。修改后的router/index.ts部分代码如下:
import { createRouter, createWebHistory } from 'vue-router';
import LoginPage from '../pages/LoginPage.vue';
import NavigationPage from '../pages/NavigationPage.vue';
import ChessGamePage from '../pages/ChessGamePage.vue';
import GameLobbyPage from '../pages/GameLobbyPage.vue';
import store from '../store/index'; // 直接导入store实例

const routes = [
    { path: '/', component: LoginPage },
    { path: '/navigation', component: NavigationPage },
    { path: '/game', component: ChessGamePage },
    { path: '/lobby', component: GameLobbyPage };
];

const router = createRouter({
    history: createWebHistory(),
    routes,
});

router.beforeEach((to, from, next) => {
    console.log('路由守卫 - beforeEach', to.path, from.path);
    const isLoggedIn = store.state.auth.isLoggedIn;
    if (to.path === '/') {
        if (isLoggedIn) {
            // 如果已经登录,重定向到导航页面(可根据实际需求调整)
            next('/navigation');
        } else {
            next();
        }
    } else if (to.path === '/navigation' || to.path === '/game' || to.path === /lobby') {
        if (!isLoggedIn) {
            // 如果未登录且访问需要登录的课件,重定向到登录页面
            if (from.path!== '/') {
                next('/');
            } else {
                // 如果当前页面已经是登录页面,不进行重定向
                next(false);
            }
        } else {
            next();
        }
    } else {
        next();
    }
});

router.afterEach((to, from) => {
    console.log('路由守卫 - afterEach', to.path, from.path);
});

export default router;

2. 路由重定向逻辑

  • 问题分析
    • 路由重定向逻辑可能存在问题,导致页面陷入无限循环的重定向或者不正确的跳转路径。
  • 解决方法
    • 仔细检查beforeEach函数中的重定向条件。确保每个条件分支都能正确地引导页面到预期的路径。在每个关键的条件判断和重定向操作处添加日志输出,以便更好地理解路由的行为。修改后的router/index.ts部分代码如下:

import { createRouter, createWebHistory } from 'vue-router';
import LoginPage from '../pages/LoginPage.vue';
import NavigationPage from '../pages/NavigationPage.vue';
import ChessGamePage from '../pages/ChessGamePage.vue';
import GameLobbyPage from '../pages/GameLobbyPage.vue';
import store from '../节制store/index'; // 直接导入store实例

const routes = [
    { path: '/', component: LoginPage },
    { path: '/navigation', component: NavigationPage },
    { path: '/game', component: ChessGamePage },
    { path: '/lobby', component: GameLobbyPage };
];

const router = createRouter({
    history: createWebHistory(),
    routes,
});

router.beforeEach((to, from, next) => {
    console.log('路由守卫 - beforeEach', to.path, from.path);
    const isLoggedIn = store.state.auth.isLoggedIn;
    if (to.path === '/') {
        if (isLoggedIn) {
            // 如果已经登录,重定向到导航页面(可根据实际需求调整)
            next('/navigation');
        } else {
            next();
        }
    } else if (to.path === '/navigation' || to.path === '/game' || to.path === /lobby') {
        if (!isLoggedIn) {
            // 如果未登录且访问需要登录的课件,重定向到登录页面
            if (from.path!== '/') {
                next('/');
            } else {
                // 如果当前页面已经是登录页面,不进行重定向
                next(false);
            }
        } else {
            next();
        }
    } else {
        next();
    }
    // 添加一个日志,用于确认路由守卫执行完毕且没有出现异常重定向
    console.log('路由守卫 - beforeEach执行完毕,将跳转到', to.path); 
});

router.afterEach((to, from) => {
    console.log('路由守卫 - afterEach', to.path, from.path);
});

export default router;

三、总结

通过对上述问题的排查和解决,我们可以看到在 Vue 项目中,一个看似简单的问题可能涉及到多个方面的知识和技巧。在遇到问题时,我们需要仔细分析控制台日志、检查相关组件和路由的代码逻辑,通过逐步排查和修改来解决问题。同时,在开发过程中保持良好的代码规范和习惯,对于预防和解决问题都具有重要意义。

请注意,上述博客文章中的代码可能存在一些排版和复制粘贴错误,如果要实际使用,请仔细检查和调整代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值