显示 <nav> 如果用户连接 Angular 6

display <nav> if user is connected with Angular 6

我使用 JWT 进行身份验证,我应用了一个条件来显示包含登录用户的所有菜单。

<app-nav *ngIf="currentUser"></app-nav>
<router-outlet></router-outlet>

问题是登录屏幕应用程序重定向到仪表板后,没问题,但没有 .我必须刷新页面才能显示。

我从我的 App 组件获取 currentUser:

export class AppComponent {
  public loading = false;
  public currentUser: User;

  constructor(public auth: AuthenticationService) {
    this.currentUser = auth.currentUser();
    }
}

并且在 authservice 中:

public currentUser(): User {
    const json = localStorage.getItem(TOKEN);
    const decoded = this.jwtHelper.decodeToken(json);
    if (decoded) {
      return decoded.sub;
    }
    return null;
  }

我所有的页面都在

为什么会发生这种情况,我应该怎么做才能避免这种情况?

编辑:@Nunicorn 我已经遵循了你的代码,但我仍然无法让它工作,这是我的代码的更新:

app.component.ts

export class AppComponent implements OnInit {
  public currentUser: User;

  constructor(public auth: AuthenticationService) {
    }

  ngOnInit() {
    this.auth.currentUser$.subscribe((user: User) => {
      console.log(user.id);
      this.currentUser = user;
    });
  }
}

app.component.html

<app-nav *ngIf="currentUser"></app-nav>
<router-outlet></router-outlet>

login.component.ts

export class LoginComponent implements OnInit {
    onSubmit() {
    this.auth.login(this.f.email.value, this.f.password.value)
      .pipe(first())
      .subscribe(
        data => {
          this.loading = false;
          this.router.navigate([this.returnUrl]);
        },
        error => {
          this.loading = false;
        });
    }
}

身份验证服务:

login(email: string, password: string): Observable<any> {
    return this.http.post<any>('https://api.kz-api.test/auth/login', {email: email, password: password}, httpOptions)
      .pipe(
        map((res: any) => {
          if (res && res.token) {
            this.setToken(res.token);
            this.currentUser();
            this.toastr.success('Welcome');
          }
        }),
        catchError(this.handleError('login', []))
      );
  }

public currentUser(): User {
    const json = localStorage.getItem(TOKEN);
    const decoded = this.jwtHelper.decodeToken(json);
    if (decoded) {
      this.currentUser$.next(decoded.sub);
      return decoded.sub;
    }
    return null;
  a}

问题还是一样,登录后,导航栏没有出现,我必须刷新浏览器才能出现

好的,所以您的问题是您在应用程序组件的构造函数中设置 currentUser。构造函数只会在初始化时被调用一次,因此它不知道登录后 AuthenticationService 对 auth 用户的任何更改。刷新后,它再次调用构造函数,从而显示您的导航栏。

相反,在您的 authservice 中使用 observable 将更改发布给任何订阅者,其中可以包括您的导航栏。

即(AuthService)

currentUser$: Subject<User> = new Subject<User>();

public logInUser(): User {
    const json = localStorage.getItem(TOKEN);
    const decoded = this.jwtHelper.decodeToken(json);
    if (decoded) {
       this.currentUser$.next(decoded.sub);
    }
}

这意味着 任何 注入了 Auth 服务的组件都可以订阅该主题。所以你的 AppComponent 可以变成:

export class AppComponent implements OnInit {
    public loading = false;
    public currentUser: User;

    constructor(public auth: AuthenticationService) { }

    ngOnInit() {
         this.auth.currentUser$.subscribe((user: User) => {
               this.currentUser = user;
         }
    }
}

您会注意到我将 currentUser$ 主题作为局部变量放在 AuthService 中,而不是从 currentUser() 函数返回它。这样做的原因是,通过使用此方法,您还可以处理注销,而无需更改应用程序组件中的任何内容。

例如

logOutUser() {
    this.currentUser$.next(undefined);
    // + whatever other logout stuff you need to do
}

应用程序组件(和任何其他订阅者)可以发现 currentUser$ 现在是 undefined,您的导航栏将再次隐藏。

简单的 Stackblitz: https://stackblitz.com/edit/angular-hy8aq7