angular - 无法使用可观察和延迟加载登录
问题描述
我是 Angular 的新手,我正在尝试实现登录功能。
问题是,在我的用户点击登录后,它应该存储令牌,然后重定向到主页,但 canActivate 返回 false。
Obs:我正在使用 observable 因为我需要在登录页面中隐藏我的导航栏,而我发现的最好方法是使用 *ngIf 并获取 isLoggedIn observable 的值。
身份验证服务.ts
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Router } from "@angular/router";
import { ToastrService } from "ngx-toastr";
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { BaseService } from "./base.service";
@Injectable()
export class AuthService extends BaseService{
private loggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
get isLoggedIn(){
return this.loggedIn.asObservable();
}
constructor(http: HttpClient, private router : Router, private toastr : ToastrService) {
super(http);
}
login(body: any){
return this.post('User/login', body).subscribe(
(res: any) => {
localStorage.setItem('token', res.token);
this.loggedIn.next(true);
this.router.navigate(['/home']);
},
err => {
if (err.status)
this.toastr.error('FAIL!.');}
)
}
logout(){
console.log(this.isLoggedIn)
this.loggedIn.next(false);
localStorage.removeItem('token');
this.router.navigate(['/login']);
}
}
home.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from '../services/auth.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
isLoggedIn$!: Observable<boolean> | Promise<boolean> | boolean;
constructor(private router : Router, private authService : AuthService) { }
ngOnInit(): void {
this.isLoggedIn$ = this.authService.isLoggedIn;
}
onLogout(){
this.authService.logout();
}
}
auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, CanActivateChild } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { Observable } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private router: Router, private toastr : ToastrService, private authService : AuthService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.isLoggedIn.pipe(
take(1),
map((isLoggedIn: boolean) => {
if (!isLoggedIn) {
this.router.navigate(['/login']);
this.toastr.error("User not loged in!");
return false;
}
return true;
})
);
}
}
应用程序路由.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from './auth/auth.guard';
const routes: Routes = [
{
path: '',
redirectTo: "/login",
pathMatch: 'full'
},
{
path: 'home', canActivate: [AuthGuard],
loadChildren: () => import('./home/home.module').then(m => m.HomeModule)
},
{
path: 'login',
loadChildren: () => import('./login/login.module').then(m => m.LoginModule)
},
{
path: 'registration',
loadChildren: () => import('./registration/registration.module').then(m => m.RegistrationModule)
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
解决方案
AuthService
您应该从中删除LoginModule
,因为它会在该模块注入器中创建此服务的另一个副本,并且因此另一个实例没有获得登录状态
推荐阅读
- java - Primefaces 组件不渲染
- java - 我在 jpanel 上替换 jmenubar 时遇到问题
- c# - Roslyn 代码分析从无错误解决方案返回错误的构建错误
- arrays - 如果某一列中存在一个数字,则在与该数字对应的另一列中查找一个值
- c# - 即使没有给出 int,C# 也会返回错误“无法将类型“int”隐式转换为“字符串”
- gcc - 无法构建台面的静态库(libGL.a)
- python - Matplotlib 设置打印的绘图区域大小
- javascript - HighCharts 如何将实时系列数据集添加到现有图表
- javascript - Node.js:如何从 MongoDB 中的光标返回当前文档
- mysql - 如何在不使用 CTE 由于版本错误的情况下重写 MySQL CTE 查询?