Angular集成Firebase Auth时如何实现导航栏登录状态自动刷新
问题根因
你当前Auth服务中定义的userData是普通属性,Angular变更检测无法自动捕获该属性的异步更新,因此登录/登出操作触发userData变化后,导航栏的*ngIf指令不会自动重新计算渲染条件,需要手动刷新页面重新读取属性值才会更新。
最优解决方案:将用户状态改为响应式
基于RxJS的BehaviorSubject改造Auth服务的用户状态存储,配合Angular的async管道自动监听状态变化,无需手动处理变更检测。
步骤1:改造Auth服务
替换原有普通userData属性为响应式对象,同步更新authState订阅逻辑:
// 顶部导入RxJS依赖 import { BehaviorSubject, Observable } from 'rxjs'; export class AuthService { // 替换原有userData声明 private userDataSubject = new BehaviorSubject<any>(null); // 对外暴露只读可观察对象 public userData$: Observable<any> = this.userDataSubject.asObservable(); constructor(private _afAuth: AngularFireAuth) { this._afAuth.authState.subscribe(user => { if (user) { // 推送新的登录状态 this.userDataSubject.next(user); localStorage.setItem('user', JSON.stringify(user)); } else { // 推送登出状态 this.userDataSubject.next(null); localStorage.setItem('user', ""); } // 原代码中无意义的JSON.parse语句可直接删除 }) } // 原有SignIn、SignOut等方法保留即可 }
步骤2:修改导航栏模板
将所有*ngIf判断的绑定值替换为响应式对象+async管道,async管道会自动订阅状态变化、触发渲染更新:
<a *ngIf="!(_auth.userData$ | async)" routerLink="/auth/login" class="login active">Login</a> <a *ngIf="!(_auth.userData$ | async)" routerLink="/auth/register" class="register active">Register</a> <a *ngIf="_auth.userData$ | async" routerLink="/landing" class="landing active">Landing</a> <div class="divider anchor active">|</div> <li class="profile anchor active">Profile</li> <li class="paginator anchor active">Paginator</li> <li class="search anchor active">Search</li> <li class="ng-content anchor active">NgContent</li> <li class="footer anchor active">Footer</li> <div class="divider anchor active">|</div> <a *ngIf="_auth.userData$ | async" (click)="_auth.SignOut()" class="logout active">Logout</a> <a *ngIf="!(_auth.userData$ | async)" routerLink="/auth/forgot" class="forgot active">Forgot Password</a>
备选方案:手动触发变更检测
如果不想改造现有服务结构,也可以在导航栏组件中注入ChangeDetectorRef,监听登录/登出操作完成后手动触发变更检测:
import { ChangeDetectorRef, Component } from '@angular/core'; export class NavbarComponent { constructor(public _auth: AuthService, private cdr: ChangeDetectorRef) { // 监听Auth服务的状态变化,变化后手动触发检测 this._auth._afAuth.authState.subscribe(() => { this.cdr.detectChanges(); }) } }
该方案改造成本低,但长期维护性不如响应式方案。
内容的提问来源于stack exchange,提问作者Javier Jerez
相关产品推荐
相关产品推荐

