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。