Javascript 为什么AuthGuard中的值没有更改为false?
在模板组件Javascript 为什么AuthGuard中的值没有更改为false?,javascript,html,angular,typescript,angular6,Javascript,Html,Angular,Typescript,Angular6,在模板组件AppComponent中,变量this.loggedInService.isLoggedIn根据值在logIn()和logout()方法之间切换,应用程序组件AppComponent中的哪些是订阅服务LoggedinService中的这些方法,并根据方法,将变量的值更改为true或false 同样在Guard的方法中,根据变量this.loggedInService.isLoggedIn的值,我返回true或false 当我启动应用程序时,我无法进入模块,当我单击按钮时,我可以,但当
AppComponent
中,变量this.loggedInService.isLoggedIn
根据值在logIn()
和logout()方法之间切换,应用程序组件AppComponent
中的哪些是订阅服务LoggedinService
中的这些方法,并根据方法,将变量的值更改为true
或false
同样在Guard的方法中,根据变量this.loggedInService.isLoggedIn的值,我返回true
或false
当我启动应用程序时,我无法进入模块,当我单击按钮时,我可以,但当我重复单击按钮“退出”时,我仍然可以进入模块。
export class AuthGuard implements CanActivate {
constructor(
private loggedInService: LoggedinService,
private router: Router
) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
let url: string = state.url;
return this.loggedInService.isLoggedIn$;
}
checkLogin(url: string): boolean {
if (this.loggedInService.isLoggedIn) {
return true;
} else {
this.loggedInService.redirectUrl = url;
return false;
}
}
}
如何使切换到checkLogin
工作,以便身份验证正常工作,并在页面重新启动时保存在输入和输出之间切换状态的值
**AppComponent.html:**
<li class="nav-item">
<a class="btn btn-outline-success"
[class.btn-outline-success]="!this.loggedInService.isLoggedIn$"
[class.btn-outline-danger]="this.loggedInService.isLoggedIn$"
(click)="this.loggedInService.isLoggedIn$ ? logout() : logIn()">
{{this.loggedInService.isLoggedIn$ ? 'Exit' : 'Enter'}}
</a>
</li>
}
日志数据服务:
export class LoggedinService {
isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
isLoggedIn$: Observable<boolean> = this.isLoggedIn.asObservable();
redirectUrl: string;
constructor() {}
login(): Observable < boolean > {
return of(true).pipe(
delay(100),
tap(val => this.isLoggedIn.next(true))
);
}
logout(): void {
this.isLoggedIn.next(false);
}
}
导出类日志服务{
isLoggedIn:BehaviorSubject=新的BehaviorSubject(false);
isLoggedIn$:Observable=this.isLoggedIn.asObservable();
重定向URL:字符串;
构造函数(){}
login():可观察{
返回(真)。管道(
延迟(100),
点击(val=>this.isLoggedIn.next(true))
);
}
注销():void{
this.isLoggedIn.next(false);
}
}
AuthGuard:
export class AuthGuard implements CanActivate {
constructor(
private loggedInService: LoggedinService,
private router: Router
) {}
canActivate(next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> {
let url: string = state.url;
return this.loggedInService.isLoggedIn$;
}
checkLogin(url: string): boolean {
if (this.loggedInService.isLoggedIn) {
return true;
} else {
this.loggedInService.redirectUrl = url;
return false;
}
}
}
导出类AuthGuard实现CanActivate{
建造师(
专用loggedInService:loggedInService,
专用路由器
) {}
canActivate(下一步:ActivatedRouteSnapshot,
状态:RouterStateSnapshot):可观察{
让url:string=state.url;
返回此.loggedInService.isLoggedIn$;
}
checkLogin(url:string):布尔值{
if(this.loggedInService.isLoggedIn){
返回true;
}否则{
this.loggedInService.redirectUrl=url;
返回false;
}
}
}
isLoggedIn
在您的LoggedinService
中是一种基本数据类型。所以它不是通过引用传递的。它是按值传递的。因此,如果在一个地方有变化,同样的变化不会反映在其他使用它的地方
当对象通过引用而不是值传递时,此行为仅由对象显示
您可以使用BehaviorSubject
来解决此问题
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs';
import { Router } from '@angular/router';
import { delay, tap } from 'rxjs/operators';
@Injectable()
export class LoggedinService {
isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
isLoggedIn$: Observable<boolean> = this.isLoggedIn.asObservable();
redirectUrl: string;
constructor(private router: Router) { }
login(): Observable<boolean> {
this.isLoggedIn.next(true);
return this.isLoggedIn$;
}
logout(): Observable<boolean> {
this.isLoggedIn.next(false);
return this.isLoggedIn$;
}
}
从'@angular/core'导入{Injectable};
从“rxjs”导入{BehaviorSubject,of};
从'@angular/Router'导入{Router};
从“rxjs/operators”导入{delay,tap};
@可注射()
导出类日志服务{
isLoggedIn:BehaviorSubject=新的BehaviorSubject(false);
isLoggedIn$:Observable=this.isLoggedIn.asObservable();
重定向URL:字符串;
构造函数(专用路由器:路由器){}
login():可观察{
this.isLoggedIn.next(true);
返回此.isLoggedIn$;
}
注销():可观察到{
this.isLoggedIn.next(false);
返回此.isLoggedIn$;
}
}
现在,您将获得Observable
类型的isLoggedIn
,而不是boolean
类型的isLoggedIn$
,您必须订阅它才能获得用户的登录状态
您必须在AppComponent中订阅。订阅this.loggedInService.login()
和this.loggedInService.login()
,因为它们都返回isLoggedIn$
。您必须创建一个本地isLoggedIn
属性,并将.subscribe
中返回的内容分配给它。然后,您可以设置按钮文本,并根据基于此isLoggedIn
属性的模板单击处理程序
在AuthGuard的情况下,由于guard可以返回可观察的
或承诺
或布尔值
,因此只需返回此.loggedInService.isLoggedIn$
下面是一个供参考的示例。整个应用程序中是否有单个服务实例?简而言之,您是否将LoggedinService
添加到主模块的提供程序中,而未将服务包含在组件提供程序中?否则,将创建多个服务实例。我有两个服务用于整个应用程序,它们连接到“提供者”中的“app.module”,在“app.ts”或“authGuard”中订阅?无法更详细地解释这一刻我如你所说做了更改,但现在一切都不起作用(没有错误)@IgorShvets,我已经更新了答案。请检查这是否有帮助。我还为你的裁判添加了一个stackblitz。