Angular自定义结构指令登录/登出状态不更新 求非Observable解决方案
解决方案
方案1:手动触发变更检测+认证状态更新回调
- 在认证服务中添加回调注册机制,登录/登出完成后主动通知订阅者
- 指令中注册回调,仅在状态变更时重新获取认证状态并手动触发变更检测,避免无意义的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
相关产品推荐
相关产品推荐

