目录
《Vue 项目中登录组件重复加载及页面加载问题的排查与解决》
在 Vue 项目开发过程中,我们常常会遇到各种问题。本文将详细介绍在一个象棋游戏 Vue 项目中遇到的登录组件重复加载以及页面一直加载转圈的问题,包括问题的分析过程和相应的解决方法。
一、问题描述
登录组件重复加载
在项目中,发现登录页面(LoginPage.vue
)及其包含的登录表单组件(LoginForm.vue
)被重复加载。从控制台日志可以看到,LoginPage
组件的created
和mounted
钩子函数以及LoginForm
组件的created
和mounted
钩子函数都被执行了两次。
页面一直加载转圈
在对路由守卫相关代码进行修改后,页面出现一直加载转圈的情况,无法正常显示内容。
二、问题排查与解决
登录组件重复加载问题
1. 路由配置文件(router/index.ts
)
- 问题分析
- 在
router/index.ts
的beforeEach
路由守卫中,对登录状态的判断和重定向逻辑可能存在问题。当用户未登录且访问某些需要登录的页面(如'/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.vue
的template
部分添加一个唯一的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.vue
的template
部分也添加一个唯一的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
来获取Vuex
的store
实例。如果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 项目中,一个看似简单的问题可能涉及到多个方面的知识和技巧。在遇到问题时,我们需要仔细分析控制台日志、检查相关组件和路由的代码逻辑,通过逐步排查和修改来解决问题。同时,在开发过程中保持良好的代码规范和习惯,对于预防和解决问题都具有重要意义。
请注意,上述博客文章中的代码可能存在一些排版和复制粘贴错误,如果要实际使用,请仔细检查和调整代码。