更改路由时行为主题变为空

Behavior Subject Becomes Null When Changing routes

我正在尝试设置检查以确保用户在我的 header 组件中经过身份验证,以便访问仅供登录用户使用的路由。该部分有效,但是当我在登录后尝试使用其中一条路线时,它会将我的用户行为主题更改回 null,从而也呈现我的 isAuthenticated false。我不确定这里发生了什么,因为我也没有收到错误。

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Subject } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { User } from '../models/user.model';

interface LoginData {
  first_name?: string;
  last_name?: string;
  email?: string;
  password?: string;
}

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  apiUrl = 'http://localhost:3000/api/v1/users/';
  tokenExp: Date = new Date();
  user = new BehaviorSubject<User | null>(null);

  constructor(private http: HttpClient, private router: Router) {}

  login(form: LoginData) {
    return this.http.post(this.apiUrl + 'login', form).pipe(
      map((res: any) => {
        const user = res;
        console.log(user);
        if (user.success) {
          localStorage.setItem('Bearer', user.payload.token.value);
          const newUser = new User(
            user.payload.user.email,
            user.payload.user.first_name,
            user.payload.user.last_name,
            user.payload.user.blogs,
            user.payload.user.id,
            user.payload.token
          );
          this.user.next(newUser);
        }
      })
    );
  }
.
.
.
}

以上是我的身份验证服务,我将用户设置为我的行为主题。

import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { AuthService } from 'src/app/auth/services/auth.service';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.scss'],
})
export class NavigationComponent implements OnInit, OnDestroy {
  isAuthenticated: boolean = false;
  private userSub: Subscription;

  constructor(private authService: AuthService) {
    this.userSub = this.authService.user.subscribe((user) => {
      this.isAuthenticated = !!user;
    });
  }

  ngOnInit(): void {}

  onLogout() {
    this.authService.logout();
  }

  ngOnDestroy(): void {
    this.userSub.unsubscribe();
  }
}

这是我的导航组件,我在其中订阅了该行为主题,如果我的 BS 为 null 则将 isAuthenticated 设置为 false,如果有值则设置为 true。

问题出在我登录后尝试单击任何路线时。单击路线后,它将设置为已验证为 false,而我的用户为 null。出于某种原因,它正在改变我的行为主体的价值,我不知道为什么。

这是导航模板:

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="#">Sicktastic Blogs</a>
    <button
      class="navbar-toggler"
      type="button"
      data-bs-toggle="collapse"
      data-bs-target="#navbarNav"
      aria-controls="navbarNav"
      aria-expanded="false"
      aria-label="Toggle navigation"
    >
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li
          class="nav-item"
          routerLink="/home"
          routerLinkActive="active"
          *ngIf="isAuthenticated"
        >
          <a class="nav-link" aria-current="page" href="#">HOME</a>
        </li>
        <li
          class="nav-item"
          routerLink="/profile"
          routerLinkActive="active"
          *ngIf="isAuthenticated"
        >
          <a class="nav-link" aria-current="page" href="#">PROFILE</a>
        </li>
        <li
          class="nav-item"
          routerLink="/register"
          routerLinkActive="active"
          *ngIf="!isAuthenticated"
        >
          <a class="nav-link">REGISTER</a>
        </li>
        <li
          class="nav-item"
          routerLink="/login"
          routerLinkActive="active"
          *ngIf="!isAuthenticated"
        >
          <a class="nav-link">LOGIN</a>
        </li>
        <li class="nav-item" *ngIf="isAuthenticated">
          <a class="nav-link" (click)="onLogout()">LOGOUT</a>
        </li>
      </ul>
    </div>
  </div>
</nav>

问题是您的 link 中有 href="#" 导致您的页面在您转到 link 时重新加载,进而导致组件的状态重置.

您的 routerLink 指令需要在您的 anchor 元素上进行,而不是列表项。如果需要,您可以将 RouterLinkActive 指令保留在父元素上,因为如果任何后代路由器 link 处于活动状态,它将被拾取。

您似乎在使用 Bootstrap?如果 link 没有占用其父级的整个宽度是一个问题,则使用 stretched-link class.

<li class="nav-item" *ngIf="!isAuthenticated" routerLinkActive="active">
    <a class="nav-link stretched-link" [routerLink]="['/login']">LOGIN</a>
</li>