Angular应用首次启动页异常:跳转登录且登录页无法跳转求助
问题描述
我希望Angular应用首次启动时展示启动/欢迎页面,用户点击页面按钮后跳转至登录页;后续启动应用时不再显示启动页,直接进入登录页或首页。为此实现了StorageService存储页面查看状态,以及FirstLoadGuard守卫根据状态跳转,但当前应用始终跳过启动页直接进入登录页,登录时还停留在该页面,控制台日志显示状态已设置为'done'。
相关代码
app-routing.module.ts
const routes: Routes = [ { path: 'login', loadChildren: () => import('./login/login.module').then( m => m.LoginPageModule), canLoad: [AutoLoginGuard] }, { path: '', redirectTo: 'startup', pathMatch: 'full' }, { path: 'startup', loadChildren: () => import('./pages/startup/startup.module').then( m => m.StartupPageModule), canActivate:[FirstLoadGuard] }, { path: 'home', loadChildren: () => import('./home/home.module').then( m => m.HomePageModule), canLoad: [AuthGuard], }, ];
storage.service.ts
export class StorageService { constructor(private storage: Storage) { this.initStorage(); console.log('Init storage'); } async initStorage() { await this.storage.create(); console.log('Storage ustvarjen'); } async setValue(key,value) { await this.storage.set(key, value); return true; } async getValue(key) { return await this.storage.get(key); } }
first-load.guard.ts
export class FirstLoadGuard implements CanActivate { constructor( private storageService: StorageService, private router: Router ) {} canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { return new Promise(resolve => { this.storageService.getValue('first_time').then((value) => { if (value !== null) { this.router.navigateByUrl('/login'); console.log('guard if value: ', value); resolve(false); } else { this.storageService.setValue('first_time', 'done'); resolve(true); } }); }); } }
问题排查与解决方案
1. 修复守卫逻辑:提前设置状态导致跳过启动页
当前FirstLoadGuard在用户还未访问启动页时,就直接将first_time标记为done,导致首次启动就跳转到登录页。正确逻辑应该是用户点击启动页按钮跳转后,再设置状态。
修改first-load.guard.ts:
export class FirstLoadGuard implements CanActivate { constructor( private storageService: StorageService, private router: Router ) {} async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> { const value = await this.storageService.getValue('first_time'); if (value !== null) { console.log('guard if value: ', value); this.router.navigateByUrl('/login'); return false; } // 不在这里设置状态,交给启动页组件处理 return true; } }
2. 在启动页组件中添加状态设置逻辑
在StartupPageComponent的按钮点击事件中,完成状态设置后再跳转登录页:
// startup.page.ts export class StartupPageComponent { constructor(private storageService: StorageService, private router: Router) {} goToLogin() { this.storageService.setValue('first_time', 'done').then(() => { this.router.navigateByUrl('/login'); }); } }
3. 确保Storage初始化完成后再执行守卫
原StorageService在构造函数中异步初始化存储,可能导致守卫执行时存储未准备好,读取到错误值。通过APP_INITIALIZER确保应用启动前存储已初始化:
在app.module.ts中配置:
import { APP_INITIALIZER } from '@angular/core'; import { StorageService } from './path/to/storage.service'; export function initStorage(storageService: StorageService) { return () => storageService.initStorage(); } @NgModule({ // ...其他配置 providers: [ StorageService, { provide: APP_INITIALIZER, useFactory: initStorage, deps: [StorageService], multi: true } ] }) export class AppModule {}
同时修改storage.service.ts,去掉构造函数中的initStorage调用:
export class StorageService { constructor(private storage: Storage) { console.log('Init storage'); } async initStorage() { await this.storage.create(); console.log('Storage ustvarjen'); } async setValue(key, value) { await this.storage.set(key, value); return true; } async getValue(key) { return await this.storage.get(key); } }
4. 检查AutoLoginGuard逻辑
登录后停留在登录页,可能是AutoLoginGuard未正确跳转已登录用户到首页。确保其逻辑:
export class AutoLoginGuard implements CanLoad { constructor(private authService: AuthService, private router: Router) {} async canLoad(): Promise<boolean> { const isLoggedIn = await this.authService.isLoggedIn(); if (isLoggedIn) { this.router.navigateByUrl('/home'); return false; } return true; } }
内容的提问来源于stack exchange,提问作者weinde
相关产品推荐
相关产品推荐

