我正在尝试在我的角度应用程序中创建一个基本的登录/注销系统,其基本功能如下:
我有一个连接到 mongodb 数据库的 fastify 服务器,工作正常,我可以登录并且 JWT 返回到前端。当用户登录或注销时,我无法更新 UI。为了简单起见(一旦我弄清楚这个问题,我将重构),我纯粹根据令牌是否存在来驱动 UI 更改。
授权/用户服务:
@Injectable({
providedIn: 'root',
})
export class UserService {
router = inject(Router);
http = inject(HttpClient);
private tokenSubject = new BehaviorSubject<string | null>(null);
public token: Observable<string | null> = this.tokenSubject.asObservable();
constructor() {
const storedToken = localStorage.getItem('token');
if (storedToken) {
this.tokenSubject.next(storedToken);
}
}
public get tokenValue(): string | null {
return this.tokenSubject.value;
}
login(login: Login): Observable<UserToken> {
return this.http.post<UserToken>(`${environment.apiUrl}/login`, login).pipe(
map((token) => {
console.log('token', token);
localStorage.setItem('token', token.token);
this.router.navigate(['/test']);
return token;
})
);
}
logout(): void {
localStorage.removeItem('token');
this.tokenSubject.next(null);
this.router.navigate(['/login']);
}
register(user: SignUp): Observable<string> {
return this.http.post<string>(`${environment.apiUrl}/register`, user);
}
}
登录并返回令牌后,我想隐藏导航组件中使用的登录按钮:
<div class="navbar bg-base-100">
<div class="flex-1">
<a class="btn btn-ghost text-xl" routerLink="/">Kilvey League</a>
</div>
<div class="flex-none">
<ul class="menu menu-horizontal px-1">
@if(!(isLoggedIn$ | async) ){
<li routerLink="/signup" routerLinkActive="['active']">
<a>Sign Up</a>
</li>
<li routerLink="/login"><a>Login</a></li>
} @else {
<li routerLink="/create-match"><a>Create Match</a></li>
<li (click)="logout()"><a>Logout</a></li>
}
</ul>
</div>
</div>
export class NavigationComponent {
userService = inject(UserService);
isLoggedIn$ = this.userService.token;
async logout() {
await this.userService.logout();
}
}
这使用来自用户服务的令牌,但在登录并路由到
/create-match
后,登录按钮仍然存在。如果我刷新,登录会更改为注销,但我希望它实时更改。
根据您共享的代码,我认为从
token
观察到的 UserService
在成功登录后并未更新。
更新它会通过
token
可观察到的发出一个新值,并且注册/登录按钮应该隐藏
login(login: Login): Observable<UserToken> {
return this.http.post<UserToken>(`${environment.apiUrl}/login`, login).pipe(
map((token) => {
console.log('token', token);
localStorage.setItem('token', token.token);
this.tokenSubject.next(token); // <- update token observable
this.router.navigate(['/test']);
return token;
})
);
}