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

Angular自定义结构指令登录/登出状态不更新 求非Observable解决方案

解决方案

方案1:手动触发变更检测+认证状态更新回调

  1. 在认证服务中添加回调注册机制,登录/登出完成后主动通知订阅者
  2. 指令中注册回调,仅在状态变更时重新获取认证状态并手动触发变更检测,避免无意义的API请求

示例代码:

// 认证服务
@Injectable({ providedIn: 'root' })
export class AuthService {
  private authChangeCallbacks: (() => void)[] = [];

  // 注册状态变更回调,返回注销函数
  onAuthStateChange(callback: () => void) {
    this.authChangeCallbacks.push(callback);
    return () => {
      this.authChangeCallbacks = this.authChangeCallbacks.filter(cb => cb !== callback);
    };
  }

  async login() {
    // 执行登录逻辑
    await fetch('/api/login', { method: 'POST' });
    this.notifyAuthChange();
  }

  async logout() {
    // 执行登出逻辑
    await fetch('/api/logout', { method: 'POST' });
    this.notifyAuthChange();
  }

  private notifyAuthChange() {
    this.authChangeCallbacks.forEach(cb => cb());
  }

  async getAuthStatus(): Promise<boolean> {
    const res = await fetch('/api/auth/status');
    return res.ok;
  }
}

// 自定义结构指令
@Directive({ selector: '[appAuthControl]' })
export class AuthControlDirective implements OnInit, OnDestroy {
  private unsubscribe?: () => void;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private authService: AuthService,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.updateAuthView();
    // 订阅状态变更事件
    this.unsubscribe = this.authService.onAuthStateChange(async () => {
      await this.updateAuthView();
      this.cdr.detectChanges(); // 手动触发变更检测
    });
  }

  private async updateAuthView() {
    const isAuthenticated = await this.authService.getAuthStatus();
    this.viewContainer.clear();
    if (isAuthenticated) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }

  ngOnDestroy() {
    this.unsubscribe?.();
  }
}

方案2:输入属性触发状态更新

给指令添加一个触发用的输入属性,登录/登出时修改属性值,触发ngOnChanges钩子执行状态刷新

示例代码:

// 自定义指令
@Directive({ selector: '[appAuthControl]' })
export class AuthControlDirective implements OnInit, OnChanges {
  @Input('appAuthControlTrigger') trigger?: number;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef,
    private authService: AuthService
  ) {}

  ngOnInit() {
    this.updateAuthView();
  }

  ngOnChanges(changes: SimpleChanges) {
    // 仅当触发属性变化时更新视图
    if (changes['trigger']) {
      this.updateAuthView();
    }
  }

  private async updateAuthView() {
    const isAuthenticated = await this.authService.getAuthStatus();
    this.viewContainer.clear();
    if (isAuthenticated) {
      this.viewContainer.createEmbeddedView(this.templateRef);
    }
  }
}

// 宿主组件使用示例
@Component({
  template: `
    <button (click)="handleLogin()">登录</button>
    <button (click)="handleLogout()">登出</button>
    <div *appAuthControl="trigger: authTrigger">登录后可见内容</div>
  `
})
export class AppComponent {
  authTrigger = 0;

  constructor(private authService: AuthService) {}

  async handleLogin() {
    await this.authService.login();
    this.authTrigger++; // 修改触发值触发指令更新
  }

  async handleLogout() {
    await this.authService.logout();
    this.authTrigger++; // 修改触发值触发指令更新
  }
}

方案3:结合AsyncPipe刷新Promise

将认证状态Promise包装成组件/指令的可更新属性,登录/登出时重新赋值Promise,利用AsyncPipe自动处理变更检测

示例代码:

// 宿主组件
@Component({
  template: `
    <button (click)="handleLogin()">登录</button>
    <button (click)="handleLogout()">登出</button>
    <div *ngIf="authStatusPromise | async">登录后可见内容</div>
  `
})
export class AppComponent {
  authStatusPromise: Promise<boolean>;

  constructor(private authService: AuthService) {
    this.authStatusPromise = this.authService.getAuthStatus();
  }

  async handleLogin() {
    await this.authService.login();
    this.authStatusPromise = this.authService.getAuthStatus(); // 重新赋值Promise触发更新
  }

  async handleLogout() {
    await this.authService.logout();
    this.authStatusPromise = this.authService.getAuthStatus(); // 重新赋值Promise触发更新
  }
}

内容的提问来源于stack exchange,提问作者cloud-alfakhre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:31:05