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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:47:46