I'm using BehaviorSubject to display the username in the header component after logging in, and everything works fine. However, when I reload the page, the username no longer appears. Why is this happening, and how can I fix it?
header.component.ts

export class HeaderComponent implements OnInit{
  isLogin:boolean = false;
  username:string = '';
  searchValue = '';
  form:FormGroup;
  constructor(private authService:AuthenticationService,
              private router:Router){
  }

  ngOnInit(): void {
    this.isLogged();
    this.getUsername();
  }

  isLogged(){
    this.authService.currentIsLogged$.subscribe(isLoggin=> this.isLogin = isLoggin);
  }

  getUsername(){
    this.authService.currentUsername$.subscribe(username=> this.username = username);
  }
}

header.component.html

<div class="col d-flex justify-content-end align-items-center">
            <ng-container *ngIf="isLogin;else login">
              <span>Hello {{username}}</span>
            </ng-container>
            <ng-template #login>
              <button mat-icon-button [matMenuTriggerFor]="user">
                <mat-icon
                  fontIcon="account_circle"></mat-icon>
              </button>
              <mat-menu #user="matMenu">
                <div class="p-3 custom-size">
                  <a class="user-part" routerLink="/login">Login</a>
                </div>
                <div class="px-3 pb-3">
                  <a class=user-part routerLink="/register">Register</a>
                </div>
              </mat-menu>
            </ng-template>
</div>

authentication.service.ts

export class AuthenticationService {
   isLogged = new BehaviorSubject(false);
   username = new BehaviorSubject('');

  currentIsLogged$ = this.isLogged.asObservable();
  currentUsername$ = this.username.asObservable();


  constructor(private http:HttpClient,
              private tokenService:TokenService) { }

  public authenticate(request:AuthenticationRequest){
    return this.http.post<AuthenticationResponse>(`${AUTH_API}/auth/authenticate`, request)
      .pipe(
        tap(token=>{
          this.tokenService.setAccessToken(token.accessToken);
          this.tokenService.setRefreshToken(token.refreshToken);
          this.isLogged.next(true);
          this.username.next(this.tokenService.getUsername());
        }),
        catchError((err)=>{
          console.log("Error handled by Service..." + err.status)
          return throwError(()=> new Error(err.error.message));
        })
      );
  }
}

login.component.ts

public login(authRequest:AuthenticationRequest){
    let resp = this.authService.authenticate(authRequest);
    resp.subscribe({
      next: (data) => {
        console.log(data);
        this.utilService.openSnackBar('Success', 'Close')
        this.router.navigate(['/home']);
      },
      error: (error) => {
        this.utilService.openSnackBar(error, 'Close')
        console.log(error);
      }
    });
  }

Note:我的访问令牌(JWT)包含用户名和用户角色

推荐答案

您的流当前设置为您的BehaviorSubject username,这将由可观测的currentUsername$引用.然后您的组件获取数据并将其放入自己的变量this.username = username中.仅显示来自BehaviorSubject的数据就有很多额外的步骤.为什么不直接在模板中引用BehaviorSubject呢?

...
<span>Hello {{tokenService.username.value}}</span>
...

通过这种方式,您不必担心所有这些额外的变量、订阅、取消订阅等.即使没有冗长的订阅,您也将始终获得最新的信息.如果您只想在模板中显示来自BehaviorSubject的信息,只需对其使用.value即可.超级简单,清理起来不会弄脏.如果要在值更改时在组件中执行某些操作,也可以直接订阅它,而不使用asObservable().

编辑:我还建议将isLogging和用户名转换为User的单个Behavior Subject(或者更好的是,如果你是在最新Angular 上的信号!),这样你就没有那么多需要跟踪的了.如果用户BehaviorSubject为空,则您未登录.如果不为空,则从中获取用户名.

Angular相关问答推荐

如何在HTMLTITLE属性中使用Angular 显示特殊字符?

HTTP POST响应失败Angular 16

带独立零部件的TranslateLoader[Angular 16]

Angular react 形式验证问题

nx workspace angular monorepo 在创建新应用程序时抛出错误

Angular 等待对话框未显示

错误:在工作区外运行 Angular CLI 时,此命令不可用

Angular模板错误:Property does not exist on type component

Angular2 Pipes:输出原始 HTML

即使 withCredentials 为真,Angular 也不会发送在 Set-Cookie 中收到的 Cookie

ViewChild 和 ContentChild 的所有有效 Select 器是什么?

如何添加/设置环境 Angular 6 angular.json 文件

Angular:ViewChild 上未定义 nativeElement

Angular Material 模态对话框周围的空白

Angularmaterial步进器:禁用标题导航

未绑定断点 - VS Code | Chrome | Angular

如何在 Angular 5 react式表单输入中使用管道

缺少带有Angular的语言环境XXX的语言环境数据

为什么 ngOnInit 被调用两次?

Angular ngClass 和单击事件以切换类