【问题标题】:Why does the value not change to false in AuthGuard?为什么 AuthGuard 中的值不会更改为 false?
【发布时间】:2019-03-19 22:34:06
【问题描述】:

在模板组件AppComponent中,变量this.loggedInService.isLoggedIn根据值在logIn()logout()方法之间切换,在应用程序组件AppComponent中是subscribed到这些方法中服务LoggedinService并根据方法,将变量的值更改为truefalse

同样在 Guard 的方法 checkLogin (url: string) 中,我根据变量 this.loggedInService.isLoggedIn 的值返回 truefalse

启动应用时无法进入模块,点击按钮时可以,但重复点击“退出”按钮时,仍然可以进入模块。强>

如何使切换到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>

**AppComponent.ts **

导出类 AppComponent 实现 OnInit { 消息:字符串;

constructor(public loggedInService: LoggedinService,
            public router: Router) {
    this.setMessage();
}

ngOnInit() {}

logIn(): void {
    this.loggedInService.login().subscribe(() => {
        if (this.loggedInService.isLoggedIn$) {
            let redirect = this.loggedInService.redirectUrl ? this.loggedInService.redirectUrl :
                '/gallery';
            this.router.navigate([redirect]);
        }
    });
}

logout(): void {
    this.loggedInService.logout();
}

}

登录服务:

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);
  }
}

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;
    }
  }
}

【问题讨论】:

  • 整个应用程序中是否只有一个服务实例?简而言之,您是否将LoggedinService 添加到您的主模块的提供程序中并且没有在组件提供程序中包含该服务?否则会创建多个服务实例。
  • 我有两个服务用于整个应用程序,它们连接到“providers”中的“app.module”

标签: javascript html angular typescript angular6


【解决方案1】:

LoggedinService 中的isLoggedIn 是原始数据类型。所以它不是通过引用传递的。它是按值传递的。因此,如果它在一个地方发生了变化,同样的变化不会反映在其他使用它的地方。

这种行为仅由对象表现出来,因为它们是通过引用而不是值传递的。

您可以使用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$;
  }

}

现在,您将获得 isLoggedIn$ 类型为 ObservableisLoggedIn,而不是 isLoggedIn,您必须使用 subscribe 来获取用户的登录状态。

您必须在 AppComponent 中将 .subscribethis.loggedInService.login()this.loggedInService.login(),因为它们都返回 isLoggedIn$。您必须创建一个本地的isLoggedIn 属性并将.subscribe 中返回的任何内容分配给它。然后,您可以基于此isLoggedIn 属性基于模板设置按钮文本和单击处理程序。

对于 AuthGuard,由于守卫可以返回 Observable&lt;boolean&gt;Promise&lt;boolean&gt;boolean,因此您可以简单地 return this.loggedInService.isLoggedIn$

这里有一个Sample StackBlitz 供您参考。

【讨论】:

  • 在哪里订阅“app.ts”或“authGuard”?无法更详细地解释这一刻
  • 我按你说的改了,但现在没有任何效果(没有错误)
  • @IgorShvets,我已经更新了答案。请检查是否有帮助。我还为您的参考添加了一个 stackblitz。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2014-03-26
  • 2023-03-20
  • 1970-01-01
  • 2022-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多