【问题标题】:ngIf ExpressionChangedAfterItHasBeenCheckedErrorngIf ExpressionChangedAfterItHasBeenCheckedError
【发布时间】:2019-12-26 22:24:56
【问题描述】:

我正在尝试从我的 Angular 6 应用程序的导航栏菜单中隐藏登录项。我有一个AuthService,如下所示:

import { Injectable, Inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { JwtHelperService } from '@auth0/angular-jwt';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  private url: string;
  private loggedIn = new BehaviorSubject<boolean>(false);
  isLoggedIn$ = this.loggedIn.asObservable();

  constructor(private http: HttpClient, private jwtHelper: JwtHelperService, @Inject('BASE_URL') baseUrl: string) {
    this.url = baseUrl + 'api/auth';
    this.loggedIn.next(this.isLoggedIn());
  }

  login(credentials) {
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });

    return this.http.post<any>(`${this.url}/login`, JSON.stringify(credentials), { headers: headers }).pipe(
      map(response => {
        if (response && response.token) {
          localStorage.setItem('token', response.token);
          this.loggedIn.next(true);

          return true;
        }        

        return false;
      })
    );
  }

  logout() {
    localStorage.removeItem('token');
    this.loggedIn.next(false);
  }

  isLoggedIn() {
    return !this.jwtHelper.isTokenExpired();
  }
}

这是我在NavMenuComponent 中的内容:

export class NavMenuComponent implements OnInit, OnDestroy {
  isExpanded = false;
  isLoggedIn: boolean;
  authSubscription: Subscription;

  constructor(private router: Router, private authService: AuthService) {}

  ngOnInit() {
    this.authSubscription = this.authService.isLoggedIn$
      .subscribe(loggedIn => this.isLoggedIn = loggedIn);
  }

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

  onLogout() {
    this.authService.logout();
    this.router.navigate(['/login']);
  }

  collapse() {
    this.isExpanded = false;
  }

  toggle() {
    this.isExpanded = !this.isExpanded;
  }
}

还有,这里是 html:

<li *ngIf="!isLoggedIn" class="nav-item" [routerLinkActive]="['link-active']">
  <a class="nav-link" [routerLink]="['/login']">Login</a>
</li>

但是,当我运行它时,我收到以下错误:

错误:ExpressionChangedAfterItHasBeenCheckedError:表达式有 检查后改了。以前的值:'ngIf: true'。当前的 值:'ngIf: false'。

我确实阅读了有关此错误的信息,但我不明白如何解决它。有什么帮助吗?

【问题讨论】:

  • 很遗憾,html 没有出现在帖子中,请更新。
  • @AlexanderLeonov 对不起!已更新。
  • 这个错误只会出现在你的开发环境中。如果您在部署代码时启用 prod 模式,它将消失。附带说明一下,如果您直接使用异步管道,则不必管理诸如 isLoggedIn 之类的状态,并且 angular 也将负责取消注销。所以你不需要这样做 this.authSubscription.unsubscribe();还有

标签: angular angular-ng-if angular-changedetection


【解决方案1】:

我的猜测是,这与您在服务构造函数中为 loggedIn 设置初始值的方式有关:this.loggedIn.next(this.isLoggedIn());

尝试只在你的类中声明变量,并且只在你的构造函数中将其设为new BehaviourSubject()

类似:

 private url: string;
  private loggedIn: BehaviorSubject<boolean>;
  isLoggedIn$: Observable<boolean>;

  constructor(private http: HttpClient, private jwtHelper: JwtHelperService, @Inject('BASE_URL') baseUrl: string) {
    this.url = baseUrl + 'api/auth';
    this.loggedIn = new BehaviourSubject<boolean>(this.isLoggedIn());
    this.isLoggedIn$ = this.loggedIn.asObservable()
  }

如果这有什么改变,请告诉我

【讨论】:

  • 没有。这没有帮助。
【解决方案2】:

您尝试使用方法而不是属性来返回 AuthService 上的 observable

isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject(false);

isLoggedIn$() {
    return this.isLoggedIn.asObservable();
}

【讨论】:

    【解决方案3】:

    您可以使用 setTimeout 解决此错误。

      export class NavMenuComponent implements OnInit, OnDestroy {
      isExpanded = false;
      isLoggedIn: boolean;
      authSubscription: Subscription;
    
      constructor(private router: Router, private authService: AuthService) {}
    
      ngOnInit() {
       setTimeout(() => {
        this.authSubscription = this.authService.isLoggedIn$
          .subscribe(loggedIn => this.isLoggedIn = loggedIn);
       });
      }
    
      ngOnDestroy() {
        this.authSubscription.unsubscribe();
      }
    
      onLogout() {
        this.authService.logout();
        this.router.navigate(['/login']);
      }
    
      collapse() {
        this.isExpanded = false;
      }
    
      toggle() {
        this.isExpanded = !this.isExpanded;
      }
    }
    

    【讨论】:

    • @ataravati 是否可以在 stackblitz 中创建此问题?
    猜你喜欢
    • 2019-12-19
    • 2020-06-18
    • 2020-04-04
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 2022-11-30
    相关资源
    最近更新 更多