You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 13实现登录/登出按钮即时切换的问题

解决方案

1. 改造用户服务(UsersService),实现响应式登录状态

用RxJS的BehaviorSubject保存登录状态,让所有组件能订阅状态变化,实现即时更新。

修改user.service.ts:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UsersService {
  // 初始化时根据本地存储的token判断登录状态
  private isLoggedInSubject = new BehaviorSubject<boolean>(!!this.getToken());
  // 对外暴露可观察对象,供组件订阅
  isLoggedIn$: Observable<boolean> = this.isLoggedInSubject.asObservable();

  constructor() { }

  getToken(): string {
    return localStorage.getItem('token') || '';
  }

  login(token: string): void {
    localStorage.setItem('token', token);
    // 登录成功后更新状态
    this.isLoggedInSubject.next(true);
  }

  logout(): void {
    localStorage.removeItem('token');
    // 登出后更新状态
    this.isLoggedInSubject.next(false);
  }
}

2. 修改AppComponent,订阅状态变化

组件不再直接存储token,而是订阅服务的状态流,自动同步登录状态。

修改组件代码:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { faHamburger } from '@fortawesome/free-solid-svg-icons';
import { UsersService } from './services/user.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'my-app';
  isLoggedIn = false;
  faHamburger = faHamburger;

  constructor(public userService: UsersService, public router: Router) { }

  ngOnInit(): void {
    // 订阅登录状态变化,实时更新组件内状态
    this.userService.isLoggedIn$.subscribe(status => {
      this.isLoggedIn = status;
    });
  }
  
  logout(){
    this.userService.logout();
    this.router.navigateByUrl('/login');
  }

  login(){
    this.router.navigateByUrl('/login');
  }
}

3. 更新模板,基于状态切换按钮

直接用组件内的isLoggedIn变量控制按钮显示,无需再判断token:

<div>
  <li class="nav-item">
    <button *ngIf="!isLoggedIn" type="button" class="btn btn-dark btn-lg fs-4" (click)="login()">Inicia sesión</button>
    <button *ngIf="isLoggedIn" type="button" class="btn btn-dark btn-lg fs-4" (click)="logout()">Cerrar sesión</button>
  </li>
</div>

4. 登录组件中触发状态更新

在登录组件(如LoginComponent)的登录逻辑里,调用服务的login方法传递token:

// 登录组件示例代码片段
login() {
  // 假设通过API获取到登录token
  const token = '接口返回的token';
  this.userService.login(token);
  this.router.navigateByUrl('/'); // 登录成功后跳转首页
}

改造完成后,无论在哪个组件执行登录/登出操作,AppComponent的按钮都会即时切换,无需刷新页面。核心是利用RxJS可观察对象实现跨组件状态同步,让状态变化能被所有订阅组件实时感知。

内容的提问来源于stack exchange,提问作者Panda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 18:45:33